#ifndef CMSH_H
#define CMSH_H

#include <cmath>
#include <vector>
#include <string>
#include <utility>
#include <functional>

#if defined(CMSH_DLL)
#if defined(CMSH_DLL_EXPORT)
#define CMSH_API __declspec(dllexport)
#else
#define CMSH_API __declspec(dllimport)
#endif
#elif defined(__GNUC__)
#define CMSH_API __attribute__ ((visibility("default")))
#else
#define CMSH_API
#endif

#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

namespace cmsh {

  // A model entity in the Gmsh API is represented by two integers: its
  // dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive
  // identifier). When dealing with multiple model entities of possibly
  // different dimensions, the entities are packed as a vector of (dim, tag)
  // integer pairs.
  typedef std::vector<std::pair<int, int> > vectorpair;

}

namespace cmsh { // Top-level functions

  // cmsh::initialize
  //
  // Initialize the Gmsh API. This must be called before any call to the other
  // functions in the API. If `argc' and `argv' (or just `argv' in Python or Julia)
  // are provided, they will be handled in the same way as the command line
  // arguments in the Gmsh app. If `readConfigFiles' is set, read system Gmsh
  // configuration files (gmshrc and cmsh-options). If `run' is set, run in the
  // same way as the Gmsh app, either interactively or in batch mode depending on
  // the command line arguments. If `run' is not set, initializing the API sets the
  // options "General.AbortOnError" to 2 and "General.Terminal" to 1.
  CMSH_API void initialize(int argc = 0, char ** argv = 0,
                           const bool readConfigFiles = true,
                           const bool run = false);

  // cmsh::isInitialized
  //
  // Return 1 if the Gmsh API is initialized, and 0 if not.
  CMSH_API int isInitialized();

  // cmsh::finalize
  //
  // Finalize the Gmsh API. This must be called when you are done using the Gmsh
  // API.
  CMSH_API void finalize();

  // cmsh::open
  //
  // Open a file. Equivalent to the `File->Open' menu in the Gmsh app. Handling of
  // the file depends on its extension and/or its contents: opening a file with
  // model data will create a new model.
  CMSH_API void open(const std::string & fileName);

  // cmsh::merge
  //
  // Merge a file. Equivalent to the `File->Merge' menu in the Gmsh app. Handling
  // of the file depends on its extension and/or its contents. Merging a file with
  // model data will add the data to the current model.
  CMSH_API void merge(const std::string & fileName);

  // cmsh::write
  //
  // Write a file. The export format is determined by the file extension.
  CMSH_API void write(const std::string & fileName);

  // cmsh::clear
  //
  // Clear all loaded models and post-processing data, and add a new empty model.
  CMSH_API void clear();

  namespace option { // Option handling functions

    // cmsh::option::setNumber
    //
    // Set a numerical option to `value'. `name' is of the form "Category.Option"
    // or "Category[num].Option". Available categories and options are listed in
    // the "Gmsh options" chapter of the Gmsh reference manual
    // (https://cmsh.info/doc/texinfo/cmsh.html#Gmsh-options).
    CMSH_API void setNumber(const std::string & name,
                            const double value);

    // cmsh::option::getNumber
    //
    // Get the `value' of a numerical option. `name' is of the form
    // "Category.Option" or "Category[num].Option". Available categories and
    // options are listed in the "Gmsh options" chapter of the Gmsh reference
    // manual (https://cmsh.info/doc/texinfo/cmsh.html#Gmsh-options).
    CMSH_API void getNumber(const std::string & name,
                            double & value);

    // cmsh::option::setString
    //
    // Set a string option to `value'. `name' is of the form "Category.Option" or
    // "Category[num].Option". Available categories and options are listed in the
    // "Gmsh options" chapter of the Gmsh reference manual
    // (https://cmsh.info/doc/texinfo/cmsh.html#Gmsh-options).
    CMSH_API void setString(const std::string & name,
                            const std::string & value);

    // cmsh::option::getString
    //
    // Get the `value' of a string option. `name' is of the form "Category.Option"
    // or "Category[num].Option". Available categories and options are listed in
    // the "Gmsh options" chapter of the Gmsh reference manual
    // (https://cmsh.info/doc/texinfo/cmsh.html#Gmsh-options).
    CMSH_API void getString(const std::string & name,
                            std::string & value);

    // cmsh::option::setColor
    //
    // Set a color option to the RGBA value (`r', `g', `b', `a'), where where `r',
    // `g', `b' and `a' should be integers between 0 and 255. `name' is of the form
    // "Category.Color.Option" or "Category[num].Color.Option". Available
    // categories and options are listed in the "Gmsh options" chapter of the Gmsh
    // reference manual (https://cmsh.info/doc/texinfo/cmsh.html#Gmsh-options). For
    // conciseness "Color." can be ommitted in `name'.
    CMSH_API void setColor(const std::string & name,
                           const int r,
                           const int g,
                           const int b,
                           const int a = 255);

    // cmsh::option::getColor
    //
    // Get the `r', `g', `b', `a' value of a color option. `name' is of the form
    // "Category.Color.Option" or "Category[num].Color.Option". Available
    // categories and options are listed in the "Gmsh options" chapter of the Gmsh
    // reference manual (https://cmsh.info/doc/texinfo/cmsh.html#Gmsh-options). For
    // conciseness "Color." can be ommitted in `name'.
    CMSH_API void getColor(const std::string & name,
                           int & r,
                           int & g,
                           int & b,
                           int & a);

    // cmsh::option::restoreDefaults
    //
    // Restore all options to default settings.
    CMSH_API void restoreDefaults();

  } // namespace option

  namespace model { // Model functions

    // cmsh::model::add
    //
    // Add a new model, with name `name', and set it as the current model.
    CMSH_API void add(const std::string & name);

    // cmsh::model::remove
    //
    // Remove the current model.
    CMSH_API void remove();

    // cmsh::model::list
    //
    // List the names of all models.
    CMSH_API void list(std::vector<std::string> & names);

    // cmsh::model::getCurrent
    //
    // Get the name of the current model.
    CMSH_API void getCurrent(std::string & name);

    // cmsh::model::setCurrent
    //
    // Set the current model to the model with name `name'. If several models have
    // the same name, select the one that was added first.
    CMSH_API void setCurrent(const std::string & name);

    // cmsh::model::getFileName
    //
    // Get the file name (if any) associated with the current model. A file name is
    // associated when a model is read from a file on disk.
    CMSH_API void getFileName(std::string & fileName);

    // cmsh::model::setFileName
    //
    // Set the file name associated with the current model.
    CMSH_API void setFileName(const std::string & fileName);

    // cmsh::model::getEntities
    //
    // Get all the entities in the current model. A model entity is represented by
    // two integers: its dimension (dim == 0, 1, 2 or 3) and its tag (its unique,
    // strictly positive identifier). If `dim' is >= 0, return only the entities of
    // the specified dimension (e.g. points if `dim' == 0). The entities are
    // returned as a vector of (dim, tag) pairs.
    CMSH_API void getEntities(cmsh::vectorpair & dimTags,
                              const int dim = -1);

    // cmsh::model::setEntityName
    //
    // Set the name of the entity of dimension `dim' and tag `tag'.
    CMSH_API void setEntityName(const int dim,
                                const int tag,
                                const std::string & name);

    // cmsh::model::getEntityName
    //
    // Get the name of the entity of dimension `dim' and tag `tag'.
    CMSH_API void getEntityName(const int dim,
                                const int tag,
                                std::string & name);

    // cmsh::model::removeEntityName
    //
    // Remove the entity name `name' from the current model.
    CMSH_API void removeEntityName(const std::string & name);

    // cmsh::model::getPhysicalGroups
    //
    // Get all the physical groups in the current model. If `dim' is >= 0, return
    // only the entities of the specified dimension (e.g. physical points if `dim'
    // == 0). The entities are returned as a vector of (dim, tag) pairs.
    CMSH_API void getPhysicalGroups(cmsh::vectorpair & dimTags,
                                    const int dim = -1);

    // cmsh::model::getEntitiesForPhysicalGroup
    //
    // Get the tags of the model entities making up the physical group of dimension
    // `dim' and tag `tag'.
    CMSH_API void getEntitiesForPhysicalGroup(const int dim,
                                              const int tag,
                                              std::vector<int> & tags);

    // cmsh::model::getEntitiesForPhysicalName
    //
    // Get the model entities (as a vector (dim, tag) pairs) making up the physical
    // group with name `name'.
    CMSH_API void getEntitiesForPhysicalName(const std::string & name,
                                             cmsh::vectorpair & dimTags);

    // cmsh::model::getPhysicalGroupsForEntity
    //
    // Get the tags of the physical groups (if any) to which the model entity of
    // dimension `dim' and tag `tag' belongs.
    CMSH_API void getPhysicalGroupsForEntity(const int dim,
                                             const int tag,
                                             std::vector<int> & physicalTags);

    // cmsh::model::addPhysicalGroup
    //
    // Add a physical group of dimension `dim', grouping the model entities with
    // tags `tags'. Return the tag of the physical group, equal to `tag' if `tag'
    // is positive, or a new tag if `tag' < 0. Set the name of the physical group
    // if `name' is not empty.
    CMSH_API int addPhysicalGroup(const int dim,
                                  const std::vector<int> & tags,
                                  const int tag = -1,
                                  const std::string & name = "");

    // cmsh::model::removePhysicalGroups
    //
    // Remove the physical groups `dimTags' (given as a vector of (dim, tag) pairs)
    // from the current model. If `dimTags' is empty, remove all groups.
    CMSH_API void removePhysicalGroups(const cmsh::vectorpair & dimTags = cmsh::vectorpair());

    // cmsh::model::setPhysicalName
    //
    // Set the name of the physical group of dimension `dim' and tag `tag'.
    CMSH_API void setPhysicalName(const int dim,
                                  const int tag,
                                  const std::string & name);

    // cmsh::model::getPhysicalName
    //
    // Get the name of the physical group of dimension `dim' and tag `tag'.
    CMSH_API void getPhysicalName(const int dim,
                                  const int tag,
                                  std::string & name);

    // cmsh::model::removePhysicalName
    //
    // Remove the physical name `name' from the current model.
    CMSH_API void removePhysicalName(const std::string & name);

    // cmsh::model::setTag
    //
    // Set the tag of the entity of dimension `dim' and tag `tag' to the new value
    // `newTag'.
    CMSH_API void setTag(const int dim,
                         const int tag,
                         const int newTag);

    // cmsh::model::getBoundary
    //
    // Get the boundary of the model entities `dimTags', given as a vector of (dim,
    // tag) pairs. Return in `outDimTags' the boundary of the individual entities
    // (if `combined' is false) or the boundary of the combined geometrical shape
    // formed by all input entities (if `combined' is true). Return tags multiplied
    // by the sign of the boundary entity if `oriented' is true. Apply the boundary
    // operator recursively down to dimension 0 (i.e. to points) if `recursive' is
    // true.
    CMSH_API void getBoundary(const cmsh::vectorpair & dimTags,
                              cmsh::vectorpair & outDimTags,
                              const bool combined = true,
                              const bool oriented = true,
                              const bool recursive = false);

    // cmsh::model::getAdjacencies
    //
    // Get the upward and downward adjacencies of the model entity of dimension
    // `dim' and tag `tag'. The `upward' vector returns the tags of adjacent
    // entities of dimension `dim' + 1; the `downward' vector returns the tags of
    // adjacent entities of dimension `dim' - 1.
    CMSH_API void getAdjacencies(const int dim,
                                 const int tag,
                                 std::vector<int> & upward,
                                 std::vector<int> & downward);

    // cmsh::model::getEntitiesInBoundingBox
    //
    // Get the model entities in the bounding box defined by the two points
    // (`xmin', `ymin', `zmin') and (`xmax', `ymax', `zmax'). If `dim' is >= 0,
    // return only the entities of the specified dimension (e.g. points if `dim' ==
    // 0).
    CMSH_API void getEntitiesInBoundingBox(const double xmin,
                                           const double ymin,
                                           const double zmin,
                                           const double xmax,
                                           const double ymax,
                                           const double zmax,
                                           cmsh::vectorpair & dimTags,
                                           const int dim = -1);

    // cmsh::model::getBoundingBox
    //
    // Get the bounding box (`xmin', `ymin', `zmin'), (`xmax', `ymax', `zmax') of
    // the model entity of dimension `dim' and tag `tag'. If `dim' and `tag' are
    // negative, get the bounding box of the whole model.
    CMSH_API void getBoundingBox(const int dim,
                                 const int tag,
                                 double & xmin,
                                 double & ymin,
                                 double & zmin,
                                 double & xmax,
                                 double & ymax,
                                 double & zmax);

    // cmsh::model::getDimension
    //
    // Return the geometrical dimension of the current model.
    CMSH_API int getDimension();

    // cmsh::model::addDiscreteEntity
    //
    // Add a discrete model entity (defined by a mesh) of dimension `dim' in the
    // current model. Return the tag of the new discrete entity, equal to `tag' if
    // `tag' is positive, or a new tag if `tag' < 0. `boundary' specifies the tags
    // of the entities on the boundary of the discrete entity, if any. Specifying
    // `boundary' allows Gmsh to construct the topology of the overall model.
    CMSH_API int addDiscreteEntity(const int dim,
                                   const int tag = -1,
                                   const std::vector<int> & boundary = std::vector<int>());

    // cmsh::model::removeEntities
    //
    // Remove the entities `dimTags' (given as a vector of (dim, tag) pairs) of the
    // current model, provided that they are not on the boundary of (or embedded
    // in) higher-dimensional entities. If `recursive' is true, remove all the
    // entities on their boundaries, down to dimension 0.
    CMSH_API void removeEntities(const cmsh::vectorpair & dimTags,
                                 const bool recursive = false);

    // cmsh::model::getType
    //
    // Get the type of the entity of dimension `dim' and tag `tag'.
    CMSH_API void getType(const int dim,
                          const int tag,
                          std::string & entityType);

    // cmsh::model::getParent
    //
    // In a partitioned model, get the parent of the entity of dimension `dim' and
    // tag `tag', i.e. from which the entity is a part of, if any. `parentDim' and
    // `parentTag' are set to -1 if the entity has no parent.
    CMSH_API void getParent(const int dim,
                            const int tag,
                            int & parentDim,
                            int & parentTag);

    // cmsh::model::getNumberOfPartitions
    //
    // Return the number of partitions in the model.
    CMSH_API int getNumberOfPartitions();

    // cmsh::model::getPartitions
    //
    // In a partitioned model, return the tags of the partition(s) to which the
    // entity belongs.
    CMSH_API void getPartitions(const int dim,
                                const int tag,
                                std::vector<int> & partitions);

    // cmsh::model::getValue
    //
    // Evaluate the parametrization of the entity of dimension `dim' and tag `tag'
    // at the parametric coordinates `parametricCoord'. Only valid for `dim' equal
    // to 0 (with empty `parametricCoord'), 1 (with `parametricCoord' containing
    // parametric coordinates on the curve) or 2 (with `parametricCoord' containing
    // u, v parametric coordinates on the surface, concatenated: [p1u, p1v, p2u,
    // ...]). Return x, y, z coordinates in `coord', concatenated: [p1x, p1y, p1z,
    // p2x, ...].
    CMSH_API void getValue(const int dim,
                           const int tag,
                           const std::vector<double> & parametricCoord,
                           std::vector<double> & coord);

    // cmsh::model::getDerivative
    //
    // Evaluate the derivative of the parametrization of the entity of dimension
    // `dim' and tag `tag' at the parametric coordinates `parametricCoord'. Only
    // valid for `dim' equal to 1 (with `parametricCoord' containing parametric
    // coordinates on the curve) or 2 (with `parametricCoord' containing u, v
    // parametric coordinates on the surface, concatenated: [p1u, p1v, p2u, ...]).
    // For `dim' equal to 1 return the x, y, z components of the derivative with
    // respect to u [d1ux, d1uy, d1uz, d2ux, ...]; for `dim' equal to 2 return the
    // x, y, z components of the derivative with respect to u and v: [d1ux, d1uy,
    // d1uz, d1vx, d1vy, d1vz, d2ux, ...].
    CMSH_API void getDerivative(const int dim,
                                const int tag,
                                const std::vector<double> & parametricCoord,
                                std::vector<double> & derivatives);

    // cmsh::model::getSecondDerivative
    //
    // Evaluate the second derivative of the parametrization of the entity of
    // dimension `dim' and tag `tag' at the parametric coordinates
    // `parametricCoord'. Only valid for `dim' equal to 1 (with `parametricCoord'
    // containing parametric coordinates on the curve) or 2 (with `parametricCoord'
    // containing u, v parametric coordinates on the surface, concatenated: [p1u,
    // p1v, p2u, ...]). For `dim' equal to 1 return the x, y, z components of the
    // second derivative with respect to u [d1uux, d1uuy, d1uuz, d2uux, ...]; for
    // `dim' equal to 2 return the x, y, z components of the second derivative with
    // respect to u and v, and the mixed derivative with respect to u and v:
    // [d1uux, d1uuy, d1uuz, d1vvx, d1vvy, d1vvz, d1uvx, d1uvy, d1uvz, d2uux, ...].
    CMSH_API void getSecondDerivative(const int dim,
                                      const int tag,
                                      const std::vector<double> & parametricCoord,
                                      std::vector<double> & derivatives);

    // cmsh::model::getCurvature
    //
    // Evaluate the (maximum) curvature of the entity of dimension `dim' and tag
    // `tag' at the parametric coordinates `parametricCoord'. Only valid for `dim'
    // equal to 1 (with `parametricCoord' containing parametric coordinates on the
    // curve) or 2 (with `parametricCoord' containing u, v parametric coordinates
    // on the surface, concatenated: [p1u, p1v, p2u, ...]).
    CMSH_API void getCurvature(const int dim,
                               const int tag,
                               const std::vector<double> & parametricCoord,
                               std::vector<double> & curvatures);

    // cmsh::model::getPrincipalCurvatures
    //
    // Evaluate the principal curvatures of the surface with tag `tag' at the
    // parametric coordinates `parametricCoord', as well as their respective
    // directions. `parametricCoord' are given by pair of u and v coordinates,
    // concatenated: [p1u, p1v, p2u, ...].
    CMSH_API void getPrincipalCurvatures(const int tag,
                                         const std::vector<double> & parametricCoord,
                                         std::vector<double> & curvatureMax,
                                         std::vector<double> & curvatureMin,
                                         std::vector<double> & directionMax,
                                         std::vector<double> & directionMin);

    // cmsh::model::getNormal
    //
    // Get the normal to the surface with tag `tag' at the parametric coordinates
    // `parametricCoord'. The `parametricCoord' vector should contain u and v
    // coordinates, concatenated: [p1u, p1v, p2u, ...]. `normals' are returned as a
    // vector of x, y, z components, concatenated: [n1x, n1y, n1z, n2x, ...].
    CMSH_API void getNormal(const int tag,
                            const std::vector<double> & parametricCoord,
                            std::vector<double> & normals);

    // cmsh::model::getParametrization
    //
    // Get the parametric coordinates `parametricCoord' for the points `coord' on
    // the entity of dimension `dim' and tag `tag'. `coord' are given as x, y, z
    // coordinates, concatenated: [p1x, p1y, p1z, p2x, ...]. `parametricCoord'
    // returns the parametric coordinates t on the curve (if `dim' = 1) or u and v
    // coordinates concatenated on the surface (if `dim' == 2), i.e. [p1t, p2t,
    // ...] or [p1u, p1v, p2u, ...].
    CMSH_API void getParametrization(const int dim,
                                     const int tag,
                                     const std::vector<double> & coord,
                                     std::vector<double> & parametricCoord);

    // cmsh::model::getParametrizationBounds
    //
    // Get the `min' and `max' bounds of the parametric coordinates for the entity
    // of dimension `dim' and tag `tag'.
    CMSH_API void getParametrizationBounds(const int dim,
                                           const int tag,
                                           std::vector<double> & min,
                                           std::vector<double> & max);

    // cmsh::model::isInside
    //
    // Check if the coordinates (or the parametric coordinates if `parametric' is
    // set) provided in `coord' correspond to points inside the entity of dimension
    // `dim' and tag `tag', and return the number of points inside. This feature is
    // only available for a subset of entities, depending on the underlying
    // geometrical representation.
    CMSH_API int isInside(const int dim,
                          const int tag,
                          const std::vector<double> & coord,
                          const bool parametric = false);

    // cmsh::model::getClosestPoint
    //
    // Get the points `closestCoord' on the entity of dimension `dim' and tag `tag'
    // to the points `coord', by orthogonal projection. `coord' and `closestCoord'
    // are given as x, y, z coordinates, concatenated: [p1x, p1y, p1z, p2x, ...].
    // `parametricCoord' returns the parametric coordinates t on the curve (if
    // `dim' == 1) or u and v coordinates concatenated on the surface (if `dim' =
    // 2), i.e. [p1t, p2t, ...] or [p1u, p1v, p2u, ...].
    CMSH_API void getClosestPoint(const int dim,
                                  const int tag,
                                  const std::vector<double> & coord,
                                  std::vector<double> & closestCoord,
                                  std::vector<double> & parametricCoord);

    // cmsh::model::reparametrizeOnSurface
    //
    // Reparametrize the boundary entity (point or curve, i.e. with `dim' == 0 or
    // `dim' == 1) of tag `tag' on the surface `surfaceTag'. If `dim' == 1,
    // reparametrize all the points corresponding to the parametric coordinates
    // `parametricCoord'. Multiple matches in case of periodic surfaces can be
    // selected with `which'. This feature is only available for a subset of
    // entities, depending on the underlying geometrical representation.
    CMSH_API void reparametrizeOnSurface(const int dim,
                                         const int tag,
                                         const std::vector<double> & parametricCoord,
                                         const int surfaceTag,
                                         std::vector<double> & surfaceParametricCoord,
                                         const int which = 0);

    // cmsh::model::setVisibility
    //
    // Set the visibility of the model entities `dimTags' (given as a vector of
    // (dim, tag) pairs) to `value'. Apply the visibility setting recursively if
    // `recursive' is true.
    CMSH_API void setVisibility(const cmsh::vectorpair & dimTags,
                                const int value,
                                const bool recursive = false);

    // cmsh::model::getVisibility
    //
    // Get the visibility of the model entity of dimension `dim' and tag `tag'.
    CMSH_API void getVisibility(const int dim,
                                const int tag,
                                int & value);

    // cmsh::model::setVisibilityPerWindow
    //
    // Set the global visibility of the model per window to `value', where
    // `windowIndex' identifies the window in the window list.
    CMSH_API void setVisibilityPerWindow(const int value,
                                         const int windowIndex = 0);

    // cmsh::model::setColor
    //
    // Set the color of the model entities `dimTags' (given as a vector of (dim,
    // tag) pairs) to the RGBA value (`r', `g', `b', `a'), where `r', `g', `b' and
    // `a' should be integers between 0 and 255. Apply the color setting
    // recursively if `recursive' is true.
    CMSH_API void setColor(const cmsh::vectorpair & dimTags,
                           const int r,
                           const int g,
                           const int b,
                           const int a = 255,
                           const bool recursive = false);

    // cmsh::model::getColor
    //
    // Get the color of the model entity of dimension `dim' and tag `tag'. If no
    // color is specified for the entity, return fully transparent blue, i.e. (0,
    // 0, 255, 0).
    CMSH_API void getColor(const int dim,
                           const int tag,
                           int & r,
                           int & g,
                           int & b,
                           int & a);

    // cmsh::model::setCoordinates
    //
    // Set the `x', `y', `z' coordinates of a geometrical point.
    CMSH_API void setCoordinates(const int tag,
                                 const double x,
                                 const double y,
                                 const double z);

    // cmsh::model::setAttribute
    //
    // Set the values of the attribute with name `name'.
    CMSH_API void setAttribute(const std::string & name,
                               const std::vector<std::string> & values);

    // cmsh::model::getAttribute
    //
    // Get the values of the attribute with name `name'.
    CMSH_API void getAttribute(const std::string & name,
                               std::vector<std::string> & values);

    // cmsh::model::getAttributeNames
    //
    // Get the names of any optional attributes stored in the model.
    CMSH_API void getAttributeNames(std::vector<std::string> & names);

    // cmsh::model::removeAttribute
    //
    // Remove the attribute with name `name'.
    CMSH_API void removeAttribute(const std::string & name);

    namespace mesh { // Mesh functions

      // cmsh::model::mesh::generate
      //
      // Generate a mesh of the current model, up to dimension `dim' (0, 1, 2 or
      // 3).
      CMSH_API void generate(const int dim = 3);

      // cmsh::model::mesh::partition
      //
      // Partition the mesh of the current model into `numPart' partitions.
      // Optionally, `elementTags' and `partitions' can be provided to specify the
      // partition of each element explicitly.
      CMSH_API void partition(const int numPart,
                              const std::vector<std::size_t> & elementTags = std::vector<std::size_t>(),
                              const std::vector<int> & partitions = std::vector<int>());

      // cmsh::model::mesh::unpartition
      //
      // Unpartition the mesh of the current model.
      CMSH_API void unpartition();

      // cmsh::model::mesh::optimize
      //
      // Optimize the mesh of the current model using `method' (empty for default
      // tetrahedral mesh optimizer, "Netgen" for Netgen optimizer, "HighOrder" for
      // direct high-order mesh optimizer, "HighOrderElastic" for high-order
      // elastic smoother, "HighOrderFastCurving" for fast curving algorithm,
      // "Laplace2D" for Laplace smoothing, "Relocate2D" and "Relocate3D" for node
      // relocation, "QuadQuasiStructured" for quad mesh optimization,
      // "UntangleMeshGeometry" for untangling). If `force' is set apply the
      // optimization also to discrete entities. If `dimTags' (given as a vector of
      // (dim, tag) pairs) is given, only apply the optimizer to the given
      // entities.
      CMSH_API void optimize(const std::string & method = "",
                             const bool force = false,
                             const int niter = 1,
                             const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::recombine
      //
      // Recombine the mesh of the current model.
      CMSH_API void recombine();

      // cmsh::model::mesh::refine
      //
      // Refine the mesh of the current model by uniformly splitting the elements.
      CMSH_API void refine();

      // cmsh::model::mesh::setOrder
      //
      // Change the order of the elements in the mesh of the current model to
      // `order'.
      CMSH_API void setOrder(const int order);

      // cmsh::model::mesh::getLastEntityError
      //
      // Get the last entities `dimTags' (as a vector of (dim, tag) pairs) where a
      // meshing error occurred. Currently only populated by the new 3D meshing
      // algorithms.
      CMSH_API void getLastEntityError(cmsh::vectorpair & dimTags);

      // cmsh::model::mesh::getLastNodeError
      //
      // Get the last node tags `nodeTags' where a meshing error occurred.
      // Currently only populated by the new 3D meshing algorithms.
      CMSH_API void getLastNodeError(std::vector<std::size_t> & nodeTags);

      // cmsh::model::mesh::clear
      //
      // Clear the mesh, i.e. delete all the nodes and elements, for the entities
      // `dimTags', given as a vector of (dim, tag) pairs. If `dimTags' is empty,
      // clear the whole mesh. Note that the mesh of an entity can only be cleared
      // if this entity is not on the boundary of another entity with a non-empty
      // mesh.
      CMSH_API void clear(const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::removeElements
      //
      // Remove the elements with tags `elementTags' from the entity of dimension
      // `dim' and tag `tag'. If `elementTags' is empty, remove all the elements
      // classified on the entity. To get consistent node classification on model
      // entities, `reclassifyNodes()' should be called afterwards.
      CMSH_API void removeElements(const int dim,
                                   const int tag,
                                   const std::vector<std::size_t> & elementTags = std::vector<std::size_t>());

      // cmsh::model::mesh::reverse
      //
      // Reverse the orientation of the elements in the entities `dimTags', given
      // as a vector of (dim, tag) pairs. If `dimTags' is empty, reverse the
      // orientation of the elements in the whole mesh.
      CMSH_API void reverse(const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::reverseElements
      //
      // Reverse the orientation of the elements with tags `elementTags'.
      CMSH_API void reverseElements(const std::vector<std::size_t> & elementTags);

      // cmsh::model::mesh::affineTransform
      //
      // Apply the affine transformation `affineTransform' (16 entries of a 4x4
      // matrix, by row; only the 12 first can be provided for convenience) to the
      // coordinates of the nodes classified on the entities `dimTags', given as a
      // vector of (dim, tag) pairs. If `dimTags' is empty, transform all the nodes
      // in the mesh.
      CMSH_API void affineTransform(const std::vector<double> & affineTransform,
                                    const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::getNodes
      //
      // Get the nodes classified on the entity of dimension `dim' and tag `tag'.
      // If `tag' < 0, get the nodes for all entities of dimension `dim'. If `dim'
      // and `tag' are negative, get all the nodes in the mesh. `nodeTags' contains
      // the node tags (their unique, strictly positive identification numbers).
      // `coord' is a vector of length 3 times the length of `nodeTags' that
      // contains the x, y, z coordinates of the nodes, concatenated: [n1x, n1y,
      // n1z, n2x, ...]. If `dim' >= 0 and `returnParamtricCoord' is set,
      // `parametricCoord' contains the parametric coordinates ([u1, u2, ...] or
      // [u1, v1, u2, ...]) of the nodes, if available. The length of
      // `parametricCoord' can be 0 or `dim' times the length of `nodeTags'. If
      // `includeBoundary' is set, also return the nodes classified on the boundary
      // of the entity (which will be reparametrized on the entity if `dim' >= 0 in
      // order to compute their parametric coordinates).
      CMSH_API void getNodes(std::vector<std::size_t> & nodeTags,
                             std::vector<double> & coord,
                             std::vector<double> & parametricCoord,
                             const int dim = -1,
                             const int tag = -1,
                             const bool includeBoundary = false,
                             const bool returnParametricCoord = true);

      // cmsh::model::mesh::getNodesByElementType
      //
      // Get the nodes classified on the entity of tag `tag', for all the elements
      // of type `elementType'. The other arguments are treated as in `getNodes'.
      CMSH_API void getNodesByElementType(const int elementType,
                                          std::vector<std::size_t> & nodeTags,
                                          std::vector<double> & coord,
                                          std::vector<double> & parametricCoord,
                                          const int tag = -1,
                                          const bool returnParametricCoord = true);

      // cmsh::model::mesh::getNode
      //
      // Get the coordinates and the parametric coordinates (if any) of the node
      // with tag `tag', as well as the dimension `dim' and tag `tag' of the entity
      // on which the node is classified. This function relies on an internal cache
      // (a vector in case of dense node numbering, a map otherwise); for large
      // meshes accessing nodes in bulk is often preferable.
      CMSH_API void getNode(const std::size_t nodeTag,
                            std::vector<double> & coord,
                            std::vector<double> & parametricCoord,
                            int & dim,
                            int & tag);

      // cmsh::model::mesh::setNode
      //
      // Set the coordinates and the parametric coordinates (if any) of the node
      // with tag `tag'. This function relies on an internal cache (a vector in
      // case of dense node numbering, a map otherwise); for large meshes accessing
      // nodes in bulk is often preferable.
      CMSH_API void setNode(const std::size_t nodeTag,
                            const std::vector<double> & coord,
                            const std::vector<double> & parametricCoord);

      // cmsh::model::mesh::rebuildNodeCache
      //
      // Rebuild the node cache.
      CMSH_API void rebuildNodeCache(const bool onlyIfNecessary = true);

      // cmsh::model::mesh::rebuildElementCache
      //
      // Rebuild the element cache.
      CMSH_API void rebuildElementCache(const bool onlyIfNecessary = true);

      // cmsh::model::mesh::getNodesForPhysicalGroup
      //
      // Get the nodes from all the elements belonging to the physical group of
      // dimension `dim' and tag `tag'. `nodeTags' contains the node tags; `coord'
      // is a vector of length 3 times the length of `nodeTags' that contains the
      // x, y, z coordinates of the nodes, concatenated: [n1x, n1y, n1z, n2x, ...].
      CMSH_API void getNodesForPhysicalGroup(const int dim,
                                             const int tag,
                                             std::vector<std::size_t> & nodeTags,
                                             std::vector<double> & coord);

      // cmsh::model::mesh::getMaxNodeTag
      //
      // Get the maximum tag `maxTag' of a node in the mesh.
      CMSH_API void getMaxNodeTag(std::size_t & maxTag);

      // cmsh::model::mesh::addNodes
      //
      // Add nodes classified on the model entity of dimension `dim' and tag `tag'.
      // `nodeTags' contains the node tags (their unique, strictly positive
      // identification numbers). `coord' is a vector of length 3 times the length
      // of `nodeTags' that contains the x, y, z coordinates of the nodes,
      // concatenated: [n1x, n1y, n1z, n2x, ...]. The optional `parametricCoord'
      // vector contains the parametric coordinates of the nodes, if any. The
      // length of `parametricCoord' can be 0 or `dim' times the length of
      // `nodeTags'. If the `nodeTags' vector is empty, new tags are automatically
      // assigned to the nodes.
      CMSH_API void addNodes(const int dim,
                             const int tag,
                             const std::vector<std::size_t> & nodeTags,
                             const std::vector<double> & coord,
                             const std::vector<double> & parametricCoord = std::vector<double>());

      // cmsh::model::mesh::reclassifyNodes
      //
      // Reclassify all nodes on their associated model entity, based on the
      // elements. Can be used when importing nodes in bulk (e.g. by associating
      // them all to a single volume), to reclassify them correctly on model
      // surfaces, curves, etc. after the elements have been set.
      CMSH_API void reclassifyNodes();

      // cmsh::model::mesh::relocateNodes
      //
      // Relocate the nodes classified on the entity of dimension `dim' and tag
      // `tag' using their parametric coordinates. If `tag' < 0, relocate the nodes
      // for all entities of dimension `dim'. If `dim' and `tag' are negative,
      // relocate all the nodes in the mesh.
      CMSH_API void relocateNodes(const int dim = -1,
                                  const int tag = -1);

      // cmsh::model::mesh::getElements
      //
      // Get the elements classified on the entity of dimension `dim' and tag
      // `tag'. If `tag' < 0, get the elements for all entities of dimension `dim'.
      // If `dim' and `tag' are negative, get all the elements in the mesh.
      // `elementTypes' contains the MSH types of the elements (e.g. `2' for 3-node
      // triangles: see `getElementProperties' to obtain the properties for a given
      // element type). `elementTags' is a vector of the same length as
      // `elementTypes'; each entry is a vector containing the tags (unique,
      // strictly positive identifiers) of the elements of the corresponding type.
      // `nodeTags' is also a vector of the same length as `elementTypes'; each
      // entry is a vector of length equal to the number of elements of the given
      // type times the number N of nodes for this type of element, that contains
      // the node tags of all the elements of the given type, concatenated: [e1n1,
      // e1n2, ..., e1nN, e2n1, ...].
      CMSH_API void getElements(std::vector<int> & elementTypes,
                                std::vector<std::vector<std::size_t> > & elementTags,
                                std::vector<std::vector<std::size_t> > & nodeTags,
                                const int dim = -1,
                                const int tag = -1);

      // cmsh::model::mesh::getElement
      //
      // Get the type and node tags of the element with tag `tag', as well as the
      // dimension `dim' and tag `tag' of the entity on which the element is
      // classified. This function relies on an internal cache (a vector in case of
      // dense element numbering, a map otherwise); for large meshes accessing
      // elements in bulk is often preferable.
      CMSH_API void getElement(const std::size_t elementTag,
                               int & elementType,
                               std::vector<std::size_t> & nodeTags,
                               int & dim,
                               int & tag);

      // cmsh::model::mesh::getElementByCoordinates
      //
      // Search the mesh for an element located at coordinates (`x', `y', `z').
      // This function performs a search in a spatial octree. If an element is
      // found, return its tag, type and node tags, as well as the local
      // coordinates (`u', `v', `w') within the reference element corresponding to
      // search location. If `dim' is >= 0, only search for elements of the given
      // dimension. If `strict' is not set, use a tolerance to find elements near
      // the search location.
      CMSH_API void getElementByCoordinates(const double x,
                                            const double y,
                                            const double z,
                                            std::size_t & elementTag,
                                            int & elementType,
                                            std::vector<std::size_t> & nodeTags,
                                            double & u,
                                            double & v,
                                            double & w,
                                            const int dim = -1,
                                            const bool strict = false);

      // cmsh::model::mesh::getElementsByCoordinates
      //
      // Search the mesh for element(s) located at coordinates (`x', `y', `z').
      // This function performs a search in a spatial octree. Return the tags of
      // all found elements in `elementTags'. Additional information about the
      // elements can be accessed through `getElement' and
      // `getLocalCoordinatesInElement'. If `dim' is >= 0, only search for elements
      // of the given dimension. If `strict' is not set, use a tolerance to find
      // elements near the search location.
      CMSH_API void getElementsByCoordinates(const double x,
                                             const double y,
                                             const double z,
                                             std::vector<std::size_t> & elementTags,
                                             const int dim = -1,
                                             const bool strict = false);

      // cmsh::model::mesh::getLocalCoordinatesInElement
      //
      // Return the local coordinates (`u', `v', `w') within the element
      // `elementTag' corresponding to the model coordinates (`x', `y', `z'). This
      // function relies on an internal cache (a vector in case of dense element
      // numbering, a map otherwise); for large meshes accessing elements in bulk
      // is often preferable.
      CMSH_API void getLocalCoordinatesInElement(const std::size_t elementTag,
                                                 const double x,
                                                 const double y,
                                                 const double z,
                                                 double & u,
                                                 double & v,
                                                 double & w);

      // cmsh::model::mesh::getElementTypes
      //
      // Get the types of elements in the entity of dimension `dim' and tag `tag'.
      // If `tag' < 0, get the types for all entities of dimension `dim'. If `dim'
      // and `tag' are negative, get all the types in the mesh.
      CMSH_API void getElementTypes(std::vector<int> & elementTypes,
                                    const int dim = -1,
                                    const int tag = -1);

      // cmsh::model::mesh::getElementType
      //
      // Return an element type given its family name `familyName' ("Point",
      // "Line", "Triangle", "Quadrangle", "Tetrahedron", "Pyramid", "Prism",
      // "Hexahedron") and polynomial order `order'. If `serendip' is true, return
      // the corresponding serendip element type (element without interior nodes).
      CMSH_API int getElementType(const std::string & familyName,
                                  const int order,
                                  const bool serendip = false);

      // cmsh::model::mesh::getElementProperties
      //
      // Get the properties of an element of type `elementType': its name
      // (`elementName'), dimension (`dim'), order (`order'), number of nodes
      // (`numNodes'), local coordinates of the nodes in the reference element
      // (`localNodeCoord' vector, of length `dim' times `numNodes') and number of
      // primary (first order) nodes (`numPrimaryNodes').
      CMSH_API void getElementProperties(const int elementType,
                                         std::string & elementName,
                                         int & dim,
                                         int & order,
                                         int & numNodes,
                                         std::vector<double> & localNodeCoord,
                                         int & numPrimaryNodes);

      // cmsh::model::mesh::getElementsByType
      //
      // Get the elements of type `elementType' classified on the entity of tag
      // `tag'. If `tag' < 0, get the elements for all entities. `elementTags' is a
      // vector containing the tags (unique, strictly positive identifiers) of the
      // elements of the corresponding type. `nodeTags' is a vector of length equal
      // to the number of elements of the given type times the number N of nodes
      // for this type of element, that contains the node tags of all the elements
      // of the given type, concatenated: [e1n1, e1n2, ..., e1nN, e2n1, ...]. If
      // `numTasks' > 1, only compute and return the part of the data indexed by
      // `task' (for C++ only; output vectors must be preallocated).
      CMSH_API void getElementsByType(const int elementType,
                                      std::vector<std::size_t> & elementTags,
                                      std::vector<std::size_t> & nodeTags,
                                      const int tag = -1,
                                      const std::size_t task = 0,
                                      const std::size_t numTasks = 1);

      // cmsh::model::mesh::getMaxElementTag
      //
      // Get the maximum tag `maxTag' of an element in the mesh.
      CMSH_API void getMaxElementTag(std::size_t & maxTag);

      // cmsh::model::mesh::preallocateElementsByType
      //
      // Preallocate data before calling `getElementsByType' with `numTasks' > 1.
      // For C++ only.
      CMSH_API void preallocateElementsByType(const int elementType,
                                              const bool elementTag,
                                              const bool nodeTag,
                                              std::vector<std::size_t> & elementTags,
                                              std::vector<std::size_t> & nodeTags,
                                              const int tag = -1);

      // cmsh::model::mesh::getElementQualities
      //
      // Get the quality `elementQualities' of the elements with tags
      // `elementTags'. `qualityType' is the requested quality measure: "minDetJac"
      // and "maxDetJac" for the adaptively computed minimal and maximal Jacobian
      // determinant, "minSJ" for the sampled minimal scaled jacobien, "minSICN"
      // for the sampled minimal signed inverted condition number, "minSIGE" for
      // the sampled signed inverted gradient error, "gamma" for the ratio of the
      // inscribed to circumcribed sphere radius, "innerRadius" for the inner
      // radius, "outerRadius" for the outerRadius, "minIsotropy" for the minimum
      // isotropy measure, "angleShape" for the angle shape measure, "minEdge" for
      // the minimum straight edge length, "maxEdge" for the maximum straight edge
      // length, "volume" for the volume. If `numTasks' > 1, only compute and
      // return the part of the data indexed by `task' (for C++ only; output vector
      // must be preallocated).
      CMSH_API void getElementQualities(const std::vector<std::size_t> & elementTags,
                                        std::vector<double> & elementsQuality,
                                        const std::string & qualityName = "minSICN",
                                        const std::size_t task = 0,
                                        const std::size_t numTasks = 1);

      // cmsh::model::mesh::addElements
      //
      // Add elements classified on the entity of dimension `dim' and tag `tag'.
      // `types' contains the MSH types of the elements (e.g. `2' for 3-node
      // triangles: see the Gmsh reference manual). `elementTags' is a vector of
      // the same length as `types'; each entry is a vector containing the tags
      // (unique, strictly positive identifiers) of the elements of the
      // corresponding type. `nodeTags' is also a vector of the same length as
      // `types'; each entry is a vector of length equal to the number of elements
      // of the given type times the number N of nodes per element, that contains
      // the node tags of all the elements of the given type, concatenated: [e1n1,
      // e1n2, ..., e1nN, e2n1, ...].
      CMSH_API void addElements(const int dim,
                                const int tag,
                                const std::vector<int> & elementTypes,
                                const std::vector<std::vector<std::size_t> > & elementTags,
                                const std::vector<std::vector<std::size_t> > & nodeTags);

      // cmsh::model::mesh::addElementsByType
      //
      // Add elements of type `elementType' classified on the entity of tag `tag'.
      // `elementTags' contains the tags (unique, strictly positive identifiers) of
      // the elements of the corresponding type. `nodeTags' is a vector of length
      // equal to the number of elements times the number N of nodes per element,
      // that contains the node tags of all the elements, concatenated: [e1n1,
      // e1n2, ..., e1nN, e2n1, ...]. If the `elementTag' vector is empty, new tags
      // are automatically assigned to the elements.
      CMSH_API void addElementsByType(const int tag,
                                      const int elementType,
                                      const std::vector<std::size_t> & elementTags,
                                      const std::vector<std::size_t> & nodeTags);

      // cmsh::model::mesh::getIntegrationPoints
      //
      // Get the numerical quadrature information for the given element type
      // `elementType' and integration rule `integrationType', where
      // `integrationType' concatenates the integration rule family name with the
      // desired order (e.g. "Gauss4" for a quadrature suited for integrating 4th
      // order polynomials). The "CompositeGauss" family uses tensor-product rules
      // based the 1D Gauss-Legendre rule; the "Gauss" family uses an economic
      // scheme when available (i.e. with a minimal number of points), and falls
      // back to "CompositeGauss" otherwise. Note that integration points for the
      // "Gauss" family can fall outside of the reference element for high-order
      // rules. `localCoord' contains the u, v, w coordinates of the G integration
      // points in the reference element: [g1u, g1v, g1w, ..., gGu, gGv, gGw].
      // `weights' contains the associated weights: [g1q, ..., gGq].
      CMSH_API void getIntegrationPoints(const int elementType,
                                         const std::string & integrationType,
                                         std::vector<double> & localCoord,
                                         std::vector<double> & weights);

      // cmsh::model::mesh::getJacobians
      //
      // Get the Jacobians of all the elements of type `elementType' classified on
      // the entity of tag `tag', at the G evaluation points `localCoord' given as
      // concatenated u, v, w coordinates in the reference element [g1u, g1v, g1w,
      // ..., gGu, gGv, gGw]. Data is returned by element, with elements in the
      // same order as in `getElements' and `getElementsByType'. `jacobians'
      // contains for each element the 9 entries of the 3x3 Jacobian matrix at each
      // evaluation point. The matrix is returned by column: [e1g1Jxu, e1g1Jyu,
      // e1g1Jzu, e1g1Jxv, ..., e1g1Jzw, e1g2Jxu, ..., e1gGJzw, e2g1Jxu, ...], with
      // Jxu = dx/du, Jyu = dy/du, etc. `determinants' contains for each element
      // the determinant of the Jacobian matrix at each evaluation point: [e1g1,
      // e1g2, ... e1gG, e2g1, ...]. `coord' contains for each element the x, y, z
      // coordinates of the evaluation points. If `tag' < 0, get the Jacobian data
      // for all entities. If `numTasks' > 1, only compute and return the part of
      // the data indexed by `task' (for C++ only; output vectors must be
      // preallocated).
      CMSH_API void getJacobians(const int elementType,
                                 const std::vector<double> & localCoord,
                                 std::vector<double> & jacobians,
                                 std::vector<double> & determinants,
                                 std::vector<double> & coord,
                                 const int tag = -1,
                                 const std::size_t task = 0,
                                 const std::size_t numTasks = 1);

      // cmsh::model::mesh::preallocateJacobians
      //
      // Preallocate data before calling `getJacobians' with `numTasks' > 1. For
      // C++ only.
      CMSH_API void preallocateJacobians(const int elementType,
                                         const int numEvaluationPoints,
                                         const bool allocateJacobians,
                                         const bool allocateDeterminants,
                                         const bool allocateCoord,
                                         std::vector<double> & jacobians,
                                         std::vector<double> & determinants,
                                         std::vector<double> & coord,
                                         const int tag = -1);

      // cmsh::model::mesh::getJacobian
      //
      // Get the Jacobian for a single element `elementTag', at the G evaluation
      // points `localCoord' given as concatenated u, v, w coordinates in the
      // reference element [g1u, g1v, g1w, ..., gGu, gGv, gGw]. `jacobians'
      // contains the 9 entries of the 3x3 Jacobian matrix at each evaluation
      // point. The matrix is returned by column: [e1g1Jxu, e1g1Jyu, e1g1Jzu,
      // e1g1Jxv, ..., e1g1Jzw, e1g2Jxu, ..., e1gGJzw, e2g1Jxu, ...], with Jxu =
      // dx/du, Jyu = dy/du, etc. `determinants' contains the determinant of the
      // Jacobian matrix at each evaluation point. `coord' contains the x, y, z
      // coordinates of the evaluation points. This function relies on an internal
      // cache (a vector in case of dense element numbering, a map otherwise); for
      // large meshes accessing Jacobians in bulk is often preferable.
      CMSH_API void getJacobian(const std::size_t elementTag,
                                const std::vector<double> & localCoord,
                                std::vector<double> & jacobians,
                                std::vector<double> & determinants,
                                std::vector<double> & coord);

      // cmsh::model::mesh::getBasisFunctions
      //
      // Get the basis functions of the element of type `elementType' at the
      // evaluation points `localCoord' (given as concatenated u, v, w coordinates
      // in the reference element [g1u, g1v, g1w, ..., gGu, gGv, gGw]), for the
      // function space `functionSpaceType'. Currently supported function spaces
      // include "Lagrange" and "GradLagrange" for isoparametric Lagrange basis
      // functions and their gradient in the u, v, w coordinates of the reference
      // element; "LagrangeN" and "GradLagrangeN", with N = 1, 2, ..., for N-th
      // order Lagrange basis functions; "H1LegendreN" and "GradH1LegendreN", with
      // N = 1, 2, ..., for N-th order hierarchical H1 Legendre functions;
      // "HcurlLegendreN" and "CurlHcurlLegendreN", with N = 1, 2, ..., for N-th
      // order curl-conforming basis functions. `numComponents' returns the number
      // C of components of a basis function (e.g. 1 for scalar functions and 3 for
      // vector functions). `basisFunctions' returns the value of the N basis
      // functions at the evaluation points, i.e. [g1f1, g1f2, ..., g1fN, g2f1,
      // ...] when C == 1 or [g1f1u, g1f1v, g1f1w, g1f2u, ..., g1fNw, g2f1u, ...]
      // when C == 3. For basis functions that depend on the orientation of the
      // elements, all values for the first orientation are returned first,
      // followed by values for the second, etc. `numOrientations' returns the
      // overall number of orientations. If the `wantedOrientations' vector is not
      // empty, only return the values for the desired orientation indices.
      CMSH_API void getBasisFunctions(const int elementType,
                                      const std::vector<double> & localCoord,
                                      const std::string & functionSpaceType,
                                      int & numComponents,
                                      std::vector<double> & basisFunctions,
                                      int & numOrientations,
                                      const std::vector<int> & wantedOrientations = std::vector<int>());

      // cmsh::model::mesh::getBasisFunctionsOrientation
      //
      // Get the orientation index of the elements of type `elementType' in the
      // entity of tag `tag'. The arguments have the same meaning as in
      // `getBasisFunctions'. `basisFunctionsOrientation' is a vector giving for
      // each element the orientation index in the values returned by
      // `getBasisFunctions'. For Lagrange basis functions the call is superfluous
      // as it will return a vector of zeros. If `numTasks' > 1, only compute and
      // return the part of the data indexed by `task' (for C++ only; output vector
      // must be preallocated).
      CMSH_API void getBasisFunctionsOrientation(const int elementType,
                                                 const std::string & functionSpaceType,
                                                 std::vector<int> & basisFunctionsOrientation,
                                                 const int tag = -1,
                                                 const std::size_t task = 0,
                                                 const std::size_t numTasks = 1);

      // cmsh::model::mesh::getBasisFunctionsOrientationForElement
      //
      // Get the orientation of a single element `elementTag'.
      CMSH_API void getBasisFunctionsOrientationForElement(const std::size_t elementTag,
                                                           const std::string & functionSpaceType,
                                                           int & basisFunctionsOrientation);

      // cmsh::model::mesh::getNumberOfOrientations
      //
      // Get the number of possible orientations for elements of type `elementType'
      // and function space named `functionSpaceType'.
      CMSH_API int getNumberOfOrientations(const int elementType,
                                           const std::string & functionSpaceType);

      // cmsh::model::mesh::preallocateBasisFunctionsOrientation
      //
      // Preallocate data before calling `getBasisFunctionsOrientation' with
      // `numTasks' > 1. For C++ only.
      CMSH_API void preallocateBasisFunctionsOrientation(const int elementType,
                                                         std::vector<int> & basisFunctionsOrientation,
                                                         const int tag = -1);

      // cmsh::model::mesh::getEdges
      //
      // Get the global unique mesh edge identifiers `edgeTags' and orientations
      // `edgeOrientation' for an input list of node tag pairs defining these
      // edges, concatenated in the vector `nodeTags'. Mesh edges are created e.g.
      // by `createEdges()', `getKeys()' or `addEdges()'. The reference positive
      // orientation is n1 < n2, where n1 and n2 are the tags of the two edge
      // nodes, which corresponds to the local orientation of edge-based basis
      // functions as well.
      CMSH_API void getEdges(const std::vector<std::size_t> & nodeTags,
                             std::vector<std::size_t> & edgeTags,
                             std::vector<int> & edgeOrientations);

      // cmsh::model::mesh::getFaces
      //
      // Get the global unique mesh face identifiers `faceTags' and orientations
      // `faceOrientations' for an input list of a multiple of three (if `faceType'
      // == 3) or four (if `faceType' == 4) node tags defining these faces,
      // concatenated in the vector `nodeTags'. Mesh faces are created e.g. by
      // `createFaces()', `getKeys()' or `addFaces()'.
      CMSH_API void getFaces(const int faceType,
                             const std::vector<std::size_t> & nodeTags,
                             std::vector<std::size_t> & faceTags,
                             std::vector<int> & faceOrientations);

      // cmsh::model::mesh::createEdges
      //
      // Create unique mesh edges for the entities `dimTags', given as a vector of
      // (dim, tag) pairs.
      CMSH_API void createEdges(const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::createFaces
      //
      // Create unique mesh faces for the entities `dimTags', given as a vector of
      // (dim, tag) pairs.
      CMSH_API void createFaces(const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::getAllEdges
      //
      // Get the global unique identifiers `edgeTags' and the nodes `edgeNodes' of
      // the edges in the mesh. Mesh edges are created e.g. by `createEdges()',
      // `getKeys()' or addEdges().
      CMSH_API void getAllEdges(std::vector<std::size_t> & edgeTags,
                                std::vector<std::size_t> & edgeNodes);

      // cmsh::model::mesh::getAllFaces
      //
      // Get the global unique identifiers `faceTags' and the nodes `faceNodes' of
      // the faces of type `faceType' in the mesh. Mesh faces are created e.g. by
      // `createFaces()', `getKeys()' or addFaces().
      CMSH_API void getAllFaces(const int faceType,
                                std::vector<std::size_t> & faceTags,
                                std::vector<std::size_t> & faceNodes);

      // cmsh::model::mesh::addEdges
      //
      // Add mesh edges defined by their global unique identifiers `edgeTags' and
      // their nodes `edgeNodes'.
      CMSH_API void addEdges(const std::vector<std::size_t> & edgeTags,
                             const std::vector<std::size_t> & edgeNodes);

      // cmsh::model::mesh::addFaces
      //
      // Add mesh faces of type `faceType' defined by their global unique
      // identifiers `faceTags' and their nodes `faceNodes'.
      CMSH_API void addFaces(const int faceType,
                             const std::vector<std::size_t> & faceTags,
                             const std::vector<std::size_t> & faceNodes);

      // cmsh::model::mesh::getKeys
      //
      // Generate the pair of keys for the elements of type `elementType' in the
      // entity of tag `tag', for the `functionSpaceType' function space. Each pair
      // (`typeKey', `entityKey') uniquely identifies a basis function in the
      // function space. If `returnCoord' is set, the `coord' vector contains the
      // x, y, z coordinates locating basis functions for sorting purposes.
      // Warning: this is an experimental feature and will probably change in a
      // future release.
      CMSH_API void getKeys(const int elementType,
                            const std::string & functionSpaceType,
                            std::vector<int> & typeKeys,
                            std::vector<std::size_t> & entityKeys,
                            std::vector<double> & coord,
                            const int tag = -1,
                            const bool returnCoord = true);

      // cmsh::model::mesh::getKeysForElement
      //
      // Get the pair of keys for a single element `elementTag'.
      CMSH_API void getKeysForElement(const std::size_t elementTag,
                                      const std::string & functionSpaceType,
                                      std::vector<int> & typeKeys,
                                      std::vector<std::size_t> & entityKeys,
                                      std::vector<double> & coord,
                                      const bool returnCoord = true);

      // cmsh::model::mesh::getNumberOfKeys
      //
      // Get the number of keys by elements of type `elementType' for function
      // space named `functionSpaceType'.
      CMSH_API int getNumberOfKeys(const int elementType,
                                   const std::string & functionSpaceType);

      // cmsh::model::mesh::getKeysInformation
      //
      // Get information about the pair of `keys'. `infoKeys' returns information
      // about the functions associated with the pairs (`typeKeys', `entityKey').
      // `infoKeys[0].first' describes the type of function (0 for  vertex
      // function, 1 for edge function, 2 for face function and 3 for bubble
      // function). `infoKeys[0].second' gives the order of the function associated
      // with the key. Warning: this is an experimental feature and will probably
      // change in a future release.
      CMSH_API void getKeysInformation(const std::vector<int> & typeKeys,
                                       const std::vector<std::size_t> & entityKeys,
                                       const int elementType,
                                       const std::string & functionSpaceType,
                                       cmsh::vectorpair & infoKeys);

      // cmsh::model::mesh::getBarycenters
      //
      // Get the barycenters of all elements of type `elementType' classified on
      // the entity of tag `tag'. If `primary' is set, only the primary nodes of
      // the elements are taken into account for the barycenter calculation. If
      // `fast' is set, the function returns the sum of the primary node
      // coordinates (without normalizing by the number of nodes). If `tag' < 0,
      // get the barycenters for all entities. If `numTasks' > 1, only compute and
      // return the part of the data indexed by `task' (for C++ only; output vector
      // must be preallocated).
      CMSH_API void getBarycenters(const int elementType,
                                   const int tag,
                                   const bool fast,
                                   const bool primary,
                                   std::vector<double> & barycenters,
                                   const std::size_t task = 0,
                                   const std::size_t numTasks = 1);

      // cmsh::model::mesh::preallocateBarycenters
      //
      // Preallocate data before calling `getBarycenters' with `numTasks' > 1. For
      // C++ only.
      CMSH_API void preallocateBarycenters(const int elementType,
                                           std::vector<double> & barycenters,
                                           const int tag = -1);

      // cmsh::model::mesh::getElementEdgeNodes
      //
      // Get the nodes on the edges of all elements of type `elementType'
      // classified on the entity of tag `tag'. `nodeTags' contains the node tags
      // of the edges for all the elements: [e1a1n1, e1a1n2, e1a2n1, ...]. Data is
      // returned by element, with elements in the same order as in `getElements'
      // and `getElementsByType'. If `primary' is set, only the primary (begin/end)
      // nodes of the edges are returned. If `tag' < 0, get the edge nodes for all
      // entities. If `numTasks' > 1, only compute and return the part of the data
      // indexed by `task' (for C++ only; output vector must be preallocated).
      CMSH_API void getElementEdgeNodes(const int elementType,
                                        std::vector<std::size_t> & nodeTags,
                                        const int tag = -1,
                                        const bool primary = false,
                                        const std::size_t task = 0,
                                        const std::size_t numTasks = 1);

      // cmsh::model::mesh::getElementFaceNodes
      //
      // Get the nodes on the faces of type `faceType' (3 for triangular faces, 4
      // for quadrangular faces) of all elements of type `elementType' classified
      // on the entity of tag `tag'. `nodeTags' contains the node tags of the faces
      // for all elements: [e1f1n1, ..., e1f1nFaceType, e1f2n1, ...]. Data is
      // returned by element, with elements in the same order as in `getElements'
      // and `getElementsByType'. If `primary' is set, only the primary (corner)
      // nodes of the faces are returned. If `tag' < 0, get the face nodes for all
      // entities. If `numTasks' > 1, only compute and return the part of the data
      // indexed by `task' (for C++ only; output vector must be preallocated).
      CMSH_API void getElementFaceNodes(const int elementType,
                                        const int faceType,
                                        std::vector<std::size_t> & nodeTags,
                                        const int tag = -1,
                                        const bool primary = false,
                                        const std::size_t task = 0,
                                        const std::size_t numTasks = 1);

      // cmsh::model::mesh::getGhostElements
      //
      // Get the ghost elements `elementTags' and their associated `partitions'
      // stored in the ghost entity of dimension `dim' and tag `tag'.
      CMSH_API void getGhostElements(const int dim,
                                     const int tag,
                                     std::vector<std::size_t> & elementTags,
                                     std::vector<int> & partitions);

      // cmsh::model::mesh::setSize
      //
      // Set a mesh size constraint on the model entities `dimTags', given as a
      // vector of (dim, tag) pairs. Currently only entities of dimension 0
      // (points) are handled.
      CMSH_API void setSize(const cmsh::vectorpair & dimTags,
                            const double size);

      // cmsh::model::mesh::getSizes
      //
      // Get the mesh size constraints (if any) associated with the model entities
      // `dimTags', given as a vector of (dim, tag) pairs. A zero entry in the
      // output `sizes' vector indicates that no size constraint is specified on
      // the corresponding entity.
      CMSH_API void getSizes(const cmsh::vectorpair & dimTags,
                             std::vector<double> & sizes);

      // cmsh::model::mesh::setSizeAtParametricPoints
      //
      // Set mesh size constraints at the given parametric points `parametricCoord'
      // on the model entity of dimension `dim' and tag `tag'. Currently only
      // entities of dimension 1 (lines) are handled.
      CMSH_API void setSizeAtParametricPoints(const int dim,
                                              const int tag,
                                              const std::vector<double> & parametricCoord,
                                              const std::vector<double> & sizes);

      // cmsh::model::mesh::setSizeCallback
      //
      // Set a mesh size callback for the current model. The callback function
      // should take six arguments as input (`dim', `tag', `x', `y', `z' and `lc').
      // The first two integer arguments correspond to the dimension `dim' and tag
      // `tag' of the entity being meshed. The next four double precision arguments
      // correspond to the coordinates `x', `y' and `z' around which to prescribe
      // the mesh size and to the mesh size `lc' that would be prescribed if the
      // callback had not been called. The callback function should return a double
      // precision number specifying the desired mesh size; returning `lc' is
      // equivalent to a no-op.
      CMSH_API void setSizeCallback(std::function<double(int, int, double, double, double, double)> callback);

      // cmsh::model::mesh::removeSizeCallback
      //
      // Remove the mesh size callback from the current model.
      CMSH_API void removeSizeCallback();

      // cmsh::model::mesh::setTransfiniteCurve
      //
      // Set a transfinite meshing constraint on the curve `tag', with `numNodes'
      // nodes distributed according to `meshType' and `coef'. Currently supported
      // types are "Progression" (geometrical progression with power `coef'),
      // "Bump" (refinement toward both extremities of the curve) and "Beta" (beta
      // law).
      CMSH_API void setTransfiniteCurve(const int tag,
                                        const int numNodes,
                                        const std::string & meshType = "Progression",
                                        const double coef = 1.);

      // cmsh::model::mesh::setTransfiniteSurface
      //
      // Set a transfinite meshing constraint on the surface `tag'. `arrangement'
      // describes the arrangement of the triangles when the surface is not flagged
      // as recombined: currently supported values are "Left", "Right",
      // "AlternateLeft" and "AlternateRight". `cornerTags' can be used to specify
      // the (3 or 4) corners of the transfinite interpolation explicitly;
      // specifying the corners explicitly is mandatory if the surface has more
      // that 3 or 4 points on its boundary.
      CMSH_API void setTransfiniteSurface(const int tag,
                                          const std::string & arrangement = "Left",
                                          const std::vector<int> & cornerTags = std::vector<int>());

      // cmsh::model::mesh::setTransfiniteVolume
      //
      // Set a transfinite meshing constraint on the surface `tag'. `cornerTags'
      // can be used to specify the (6 or 8) corners of the transfinite
      // interpolation explicitly.
      CMSH_API void setTransfiniteVolume(const int tag,
                                         const std::vector<int> & cornerTags = std::vector<int>());

      // cmsh::model::mesh::setTransfiniteAutomatic
      //
      // Set transfinite meshing constraints on the model entities in `dimTags',
      // given as a vector of (dim, tag) pairs. Transfinite meshing constraints are
      // added to the curves of the quadrangular surfaces and to the faces of
      // 6-sided volumes. Quadragular faces with a corner angle superior to
      // `cornerAngle' (in radians) are ignored. The number of points is
      // automatically determined from the sizing constraints. If `dimTag' is
      // empty, the constraints are applied to all entities in the model. If
      // `recombine' is true, the recombine flag is automatically set on the
      // transfinite surfaces.
      CMSH_API void setTransfiniteAutomatic(const cmsh::vectorpair & dimTags = cmsh::vectorpair(),
                                            const double cornerAngle = 2.35,
                                            const bool recombine = true);

      // cmsh::model::mesh::setRecombine
      //
      // Set a recombination meshing constraint on the model entity of dimension
      // `dim' and tag `tag'. Currently only entities of dimension 2 (to recombine
      // triangles into quadrangles) are supported; `angle' specifies the threshold
      // angle for the simple recombination algorithm..
      CMSH_API void setRecombine(const int dim,
                                 const int tag,
                                 const double angle = 45.);

      // cmsh::model::mesh::setSmoothing
      //
      // Set a smoothing meshing constraint on the model entity of dimension `dim'
      // and tag `tag'. `val' iterations of a Laplace smoother are applied.
      CMSH_API void setSmoothing(const int dim,
                                 const int tag,
                                 const int val);

      // cmsh::model::mesh::setReverse
      //
      // Set a reverse meshing constraint on the model entity of dimension `dim'
      // and tag `tag'. If `val' is true, the mesh orientation will be reversed
      // with respect to the natural mesh orientation (i.e. the orientation
      // consistent with the orientation of the geometry). If `val' is false, the
      // mesh is left as-is.
      CMSH_API void setReverse(const int dim,
                               const int tag,
                               const bool val = true);

      // cmsh::model::mesh::setAlgorithm
      //
      // Set the meshing algorithm on the model entity of dimension `dim' and tag
      // `tag'. Supported values are those of the `Mesh.Algorithm' option, as
      // listed in the Gmsh reference manual. Currently only supported for `dim' ==
      // 2.
      CMSH_API void setAlgorithm(const int dim,
                                 const int tag,
                                 const int val);

      // cmsh::model::mesh::setSizeFromBoundary
      //
      // Force the mesh size to be extended from the boundary, or not, for the
      // model entity of dimension `dim' and tag `tag'. Currently only supported
      // for `dim' == 2.
      CMSH_API void setSizeFromBoundary(const int dim,
                                        const int tag,
                                        const int val);

      // cmsh::model::mesh::setCompound
      //
      // Set a compound meshing constraint on the model entities of dimension `dim'
      // and tags `tags'. During meshing, compound entities are treated as a single
      // discrete entity, which is automatically reparametrized.
      CMSH_API void setCompound(const int dim,
                                const std::vector<int> & tags);

      // cmsh::model::mesh::setOutwardOrientation
      //
      // Set meshing constraints on the bounding surfaces of the volume of tag
      // `tag' so that all surfaces are oriented with outward pointing normals; and
      // if a mesh already exists, reorient it. Currently only available with the
      // OpenCASCADE kernel, as it relies on the STL triangulation.
      CMSH_API void setOutwardOrientation(const int tag);

      // cmsh::model::mesh::removeConstraints
      //
      // Remove all meshing constraints from the model entities `dimTags', given as
      // a vector of (dim, tag) pairs. If `dimTags' is empty, remove all
      // constraings.
      CMSH_API void removeConstraints(const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::embed
      //
      // Embed the model entities of dimension `dim' and tags `tags' in the
      // (`inDim', `inTag') model entity. The dimension `dim' can 0, 1 or 2 and
      // must be strictly smaller than `inDim', which must be either 2 or 3. The
      // embedded entities should not intersect each other or be part of the
      // boundary of the entity `inTag', whose mesh will conform to the mesh of the
      // embedded entities. With the OpenCASCADE kernel, if the `fragment'
      // operation is applied to entities of different dimensions, the lower
      // dimensional entities will be automatically embedded in the higher
      // dimensional entities if they are not on their boundary.
      CMSH_API void embed(const int dim,
                          const std::vector<int> & tags,
                          const int inDim,
                          const int inTag);

      // cmsh::model::mesh::removeEmbedded
      //
      // Remove embedded entities from the model entities `dimTags', given as a
      // vector of (dim, tag) pairs. if `dim' is >= 0, only remove embedded
      // entities of the given dimension (e.g. embedded points if `dim' == 0).
      CMSH_API void removeEmbedded(const cmsh::vectorpair & dimTags,
                                   const int dim = -1);

      // cmsh::model::mesh::getEmbedded
      //
      // Get the entities (if any) embedded in the model entity of dimension `dim'
      // and tag `tag'.
      CMSH_API void getEmbedded(const int dim,
                                const int tag,
                                cmsh::vectorpair & dimTags);

      // cmsh::model::mesh::reorderElements
      //
      // Reorder the elements of type `elementType' classified on the entity of tag
      // `tag' according to the `ordering' vector.
      CMSH_API void reorderElements(const int elementType,
                                    const int tag,
                                    const std::vector<std::size_t> & ordering);

      // cmsh::model::mesh::computeRenumbering
      //
      // Compute a renumbering vector `newTags' corresponding to the input tags
      // `oldTags' for a given list of element tags `elementTags'. If `elementTags'
      // is empty, compute the renumbering on the full mesh. If `method' is equal
      // to "RCMK", compute a node renumering with Reverse Cuthill McKee. If
      // `method' is equal to "Hilbert", compute a node renumering along a Hilbert
      // curve. If `method' is equal to "Metis", compute a node renumering using
      // Metis. Element renumbering is not available yet.
      CMSH_API void computeRenumbering(std::vector<std::size_t> & oldTags,
                                       std::vector<std::size_t> & newTags,
                                       const std::string & method = "RCMK",
                                       const std::vector<std::size_t> & elementTags = std::vector<std::size_t>());

      // cmsh::model::mesh::renumberNodes
      //
      // Renumber the node tags. If no explicit renumbering is provided through the
      // `oldTags' and `newTags' vectors, renumber the nodes in a continuous
      // sequence, taking into account the subset of elements to be saved later on
      // if the option "Mesh.SaveAll" is not set.
      CMSH_API void renumberNodes(const std::vector<std::size_t> & oldTags = std::vector<std::size_t>(),
                                  const std::vector<std::size_t> & newTags = std::vector<std::size_t>());

      // cmsh::model::mesh::renumberElements
      //
      // Renumber the element tags in a continuous sequence. If no explicit
      // renumbering is provided through the `oldTags' and `newTags' vectors,
      // renumber the elements in a continuous sequence, taking into account the
      // subset of elements to be saved later on if the option "Mesh.SaveAll" is
      // not set.
      CMSH_API void renumberElements(const std::vector<std::size_t> & oldTags = std::vector<std::size_t>(),
                                     const std::vector<std::size_t> & newTags = std::vector<std::size_t>());

      // cmsh::model::mesh::setPeriodic
      //
      // Set the meshes of the entities of dimension `dim' and tag `tags' as
      // periodic copies of the meshes of entities `tagsMaster', using the affine
      // transformation specified in `affineTransformation' (16 entries of a 4x4
      // matrix, by row). If used after meshing, generate the periodic node
      // correspondence information assuming the meshes of entities `tags'
      // effectively match the meshes of entities `tagsMaster' (useful for
      // structured and extruded meshes). Currently only available for @code{dim}
      // == 1 and @code{dim} == 2.
      CMSH_API void setPeriodic(const int dim,
                                const std::vector<int> & tags,
                                const std::vector<int> & tagsMaster,
                                const std::vector<double> & affineTransform);

      // cmsh::model::mesh::getPeriodic
      //
      // Get master entities `tagsMaster' for the entities of dimension `dim' and
      // tags `tags'.
      CMSH_API void getPeriodic(const int dim,
                                const std::vector<int> & tags,
                                std::vector<int> & tagMaster);

      // cmsh::model::mesh::getPeriodicNodes
      //
      // Get the master entity `tagMaster', the node tags `nodeTags' and their
      // corresponding master node tags `nodeTagsMaster', and the affine transform
      // `affineTransform' for the entity of dimension `dim' and tag `tag'. If
      // `includeHighOrderNodes' is set, include high-order nodes in the returned
      // data.
      CMSH_API void getPeriodicNodes(const int dim,
                                     const int tag,
                                     int & tagMaster,
                                     std::vector<std::size_t> & nodeTags,
                                     std::vector<std::size_t> & nodeTagsMaster,
                                     std::vector<double> & affineTransform,
                                     const bool includeHighOrderNodes = false);

      // cmsh::model::mesh::getPeriodicKeys
      //
      // Get the master entity `tagMaster' and the key pairs (`typeKeyMaster',
      // `entityKeyMaster') corresponding to the entity `tag' and the key pairs
      // (`typeKey', `entityKey') for the elements of type `elementType' and
      // function space type `functionSpaceType'. If `returnCoord' is set, the
      // `coord' and `coordMaster' vectors contain the x, y, z coordinates locating
      // basis functions for sorting purposes.
      CMSH_API void getPeriodicKeys(const int elementType,
                                    const std::string & functionSpaceType,
                                    const int tag,
                                    int & tagMaster,
                                    std::vector<int> & typeKeys,
                                    std::vector<int> & typeKeysMaster,
                                    std::vector<std::size_t> & entityKeys,
                                    std::vector<std::size_t> & entityKeysMaster,
                                    std::vector<double> & coord,
                                    std::vector<double> & coordMaster,
                                    const bool returnCoord = true);

      // cmsh::model::mesh::importStl
      //
      // Import the model STL representation (if available) as the current mesh.
      CMSH_API void importStl();

      // cmsh::model::mesh::getDuplicateNodes
      //
      // Get the `tags' of any duplicate nodes in the mesh of the entities
      // `dimTags', given as a vector of (dim, tag) pairs. If `dimTags' is empty,
      // consider the whole mesh.
      CMSH_API void getDuplicateNodes(std::vector<std::size_t> & tags,
                                      const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::removeDuplicateNodes
      //
      // Remove duplicate nodes in the mesh of the entities `dimTags', given as a
      // vector of (dim, tag) pairs. If `dimTags' is empty, consider the whole
      // mesh.
      CMSH_API void removeDuplicateNodes(const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::removeDuplicateElements
      //
      // Remove duplicate elements (defined by the same nodes, in the same entity)
      // in the mesh of the entities `dimTags', given as a vector of (dim, tag)
      // pairs. If `dimTags' is empty, consider the whole mesh.
      CMSH_API void removeDuplicateElements(const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::splitQuadrangles
      //
      // Split (into two triangles) all quadrangles in surface `tag' whose quality
      // is lower than `quality'. If `tag' < 0, split quadrangles in all surfaces.
      CMSH_API void splitQuadrangles(const double quality = 1.,
                                     const int tag = -1);

      // cmsh::model::mesh::setVisibility
      //
      // Set the visibility of the elements of tags `elementTags' to `value'.
      CMSH_API void setVisibility(const std::vector<std::size_t> & elementTags,
                                  const int value);

      // cmsh::model::mesh::getVisibility
      //
      // Get the visibility of the elements of tags `elementTags'.
      CMSH_API void getVisibility(const std::vector<std::size_t> & elementTags,
                                  std::vector<int> & values);

      // cmsh::model::mesh::classifySurfaces
      //
      // Classify ("color") the surface mesh based on the angle threshold `angle'
      // (in radians), and create new discrete surfaces, curves and points
      // accordingly. If `boundary' is set, also create discrete curves on the
      // boundary if the surface is open. If `forReparametrization' is set, create
      // curves and surfaces that can be reparametrized using a single map. If
      // `curveAngle' is less than Pi, also force curves to be split according to
      // `curveAngle'. If `exportDiscrete' is set, clear any built-in CAD kernel
      // entities and export the discrete entities in the built-in CAD kernel.
      CMSH_API void classifySurfaces(const double angle,
                                     const bool boundary = true,
                                     const bool forReparametrization = false,
                                     const double curveAngle = M_PI,
                                     const bool exportDiscrete = true);

      // cmsh::model::mesh::createGeometry
      //
      // Create a geometry for the discrete entities `dimTags' (given as a vector
      // of (dim, tag) pairs) represented solely by a mesh (without an underlying
      // CAD description), i.e. create a parametrization for discrete curves and
      // surfaces, assuming that each can be parametrized with a single map. If
      // `dimTags' is empty, create a geometry for all the discrete entities.
      CMSH_API void createGeometry(const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::mesh::createTopology
      //
      // Create a boundary representation from the mesh if the model does not have
      // one (e.g. when imported from mesh file formats with no BRep representation
      // of the underlying model). If `makeSimplyConnected' is set, enforce simply
      // connected discrete surfaces and volumes. If `exportDiscrete' is set, clear
      // any built-in CAD kernel entities and export the discrete entities in the
      // built-in CAD kernel.
      CMSH_API void createTopology(const bool makeSimplyConnected = true,
                                   const bool exportDiscrete = true);

      // cmsh::model::mesh::addHomologyRequest
      //
      // Add a request to compute a basis representation for homology spaces (if
      // `type' == "Homology") or cohomology spaces (if `type' == "Cohomology").
      // The computation domain is given in a list of physical group tags
      // `domainTags'; if empty, the whole mesh is the domain. The computation
      // subdomain for relative (co)homology computation is given in a list of
      // physical group tags `subdomainTags'; if empty, absolute (co)homology is
      // computed. The dimensions of the (co)homology bases to be computed are
      // given in the list `dim'; if empty, all bases are computed. Resulting basis
      // representation (co)chains are stored as physical groups in the mesh. If
      // the request is added before mesh generation, the computation will be
      // performed at the end of the meshing pipeline.
      CMSH_API void addHomologyRequest(const std::string & type = "Homology",
                                       const std::vector<int> & domainTags = std::vector<int>(),
                                       const std::vector<int> & subdomainTags = std::vector<int>(),
                                       const std::vector<int> & dims = std::vector<int>());

      // cmsh::model::mesh::clearHomologyRequests
      //
      // Clear all (co)homology computation requests.
      CMSH_API void clearHomologyRequests();

      // cmsh::model::mesh::computeHomology
      //
      // Perform the (co)homology computations requested by addHomologyRequest().
      // The newly created physical groups are returned in `dimTags' as a vector of
      // (dim, tag) pairs.
      CMSH_API void computeHomology(cmsh::vectorpair & dimTags);

      // cmsh::model::mesh::computeCrossField
      //
      // Compute a cross field for the current mesh. The function creates 3 views:
      // the H function, the Theta function and cross directions. Return the tags
      // of the views.
      CMSH_API void computeCrossField(std::vector<int> & viewTags);

      // cmsh::model::mesh::triangulate
      //
      // Triangulate the points given in the `coord' vector as pairs of u, v
      // coordinates, and return the node tags (with numbering starting at 1) of
      // the resulting triangles in `tri'.
      CMSH_API void triangulate(const std::vector<double> & coord,
                                std::vector<std::size_t> & tri);

      // cmsh::model::mesh::tetrahedralize
      //
      // Tetrahedralize the points given in the `coord' vector as x, y, z
      // coordinates, concatenated, and return the node tags (with numbering
      // starting at 1) of the resulting tetrahedra in `tetra'.
      CMSH_API void tetrahedralize(const std::vector<double> & coord,
                                   std::vector<std::size_t> & tetra);

      namespace field { // Mesh size field functions

        // cmsh::model::mesh::field::add
        //
        // Add a new mesh size field of type `fieldType'. If `tag' is positive,
        // assign the tag explicitly; otherwise a new tag is assigned
        // automatically. Return the field tag. Available field types are listed in
        // the "Gmsh mesh size fields" chapter of the Gmsh reference manual
        // (https://cmsh.info/doc/texinfo/cmsh.html#Gmsh-mesh-size-fields).
        CMSH_API int add(const std::string & fieldType,
                         const int tag = -1);

        // cmsh::model::mesh::field::remove
        //
        // Remove the field with tag `tag'.
        CMSH_API void remove(const int tag);

        // cmsh::model::mesh::field::list
        //
        // Get the list of all fields.
        CMSH_API void list(std::vector<int> & tags);

        // cmsh::model::mesh::field::getType
        //
        // Get the type `fieldType' of the field with tag `tag'.
        CMSH_API void getType(const int tag,
                              std::string & fileType);

        // cmsh::model::mesh::field::setNumber
        //
        // Set the numerical option `option' to value `value' for field `tag'.
        CMSH_API void setNumber(const int tag,
                                const std::string & option,
                                const double value);

        // cmsh::model::mesh::field::getNumber
        //
        // Get the value of the numerical option `option' for field `tag'.
        CMSH_API void getNumber(const int tag,
                                const std::string & option,
                                double & value);

        // cmsh::model::mesh::field::setString
        //
        // Set the string option `option' to value `value' for field `tag'.
        CMSH_API void setString(const int tag,
                                const std::string & option,
                                const std::string & value);

        // cmsh::model::mesh::field::getString
        //
        // Get the value of the string option `option' for field `tag'.
        CMSH_API void getString(const int tag,
                                const std::string & option,
                                std::string & value);

        // cmsh::model::mesh::field::setNumbers
        //
        // Set the numerical list option `option' to value `values' for field
        // `tag'.
        CMSH_API void setNumbers(const int tag,
                                 const std::string & option,
                                 const std::vector<double> & values);

        // cmsh::model::mesh::field::getNumbers
        //
        // Get the value of the numerical list option `option' for field `tag'.
        CMSH_API void getNumbers(const int tag,
                                 const std::string & option,
                                 std::vector<double> & values);

        // cmsh::model::mesh::field::setAsBackgroundMesh
        //
        // Set the field `tag' as the background mesh size field.
        CMSH_API void setAsBackgroundMesh(const int tag);

        // cmsh::model::mesh::field::setAsBoundaryLayer
        //
        // Set the field `tag' as a boundary layer size field.
        CMSH_API void setAsBoundaryLayer(const int tag);

      } // namespace field

    } // namespace mesh

    namespace geo { // Built-in CAD kernel functions

      // cmsh::model::geo::addPoint
      //
      // Add a geometrical point in the built-in CAD representation, at coordinates
      // (`x', `y', `z'). If `meshSize' is > 0, add a meshing constraint at that
      // point. If `tag' is positive, set the tag explicitly; otherwise a new tag
      // is selected automatically. Return the tag of the point. (Note that the
      // point will be added in the current model only after `synchronize' is
      // called. This behavior holds for all the entities added in the geo module.)
      CMSH_API int addPoint(const double x,
                            const double y,
                            const double z,
                            const double meshSize = 0.,
                            const int tag = -1);

      // cmsh::model::geo::addLine
      //
      // Add a straight line segment in the built-in CAD representation, between
      // the two points with tags `startTag' and `endTag'. If `tag' is positive,
      // set the tag explicitly; otherwise a new tag is selected automatically.
      // Return the tag of the line.
      CMSH_API int addLine(const int startTag,
                           const int endTag,
                           const int tag = -1);

      // cmsh::model::geo::addCircleArc
      //
      // Add a circle arc (strictly smaller than Pi) in the built-in CAD
      // representation, between the two points with tags `startTag' and `endTag',
      // and with center `centerTag'. If `tag' is positive, set the tag explicitly;
      // otherwise a new tag is selected automatically. If (`nx', `ny', `nz') !=
      // (0, 0, 0), explicitly set the plane of the circle arc. Return the tag of
      // the circle arc.
      CMSH_API int addCircleArc(const int startTag,
                                const int centerTag,
                                const int endTag,
                                const int tag = -1,
                                const double nx = 0.,
                                const double ny = 0.,
                                const double nz = 0.);

      // cmsh::model::geo::addEllipseArc
      //
      // Add an ellipse arc (strictly smaller than Pi) in the built-in CAD
      // representation, between the two points `startTag' and `endTag', and with
      // center `centerTag' and major axis point `majorTag'. If `tag' is positive,
      // set the tag explicitly; otherwise a new tag is selected automatically. If
      // (`nx', `ny', `nz') != (0, 0, 0), explicitly set the plane of the circle
      // arc. Return the tag of the ellipse arc.
      CMSH_API int addEllipseArc(const int startTag,
                                 const int centerTag,
                                 const int majorTag,
                                 const int endTag,
                                 const int tag = -1,
                                 const double nx = 0.,
                                 const double ny = 0.,
                                 const double nz = 0.);

      // cmsh::model::geo::addSpline
      //
      // Add a spline (Catmull-Rom) curve in the built-in CAD representation, going
      // through the points `pointTags'. If `tag' is positive, set the tag
      // explicitly; otherwise a new tag is selected automatically. Create a
      // periodic curve if the first and last points are the same. Return the tag
      // of the spline curve.
      CMSH_API int addSpline(const std::vector<int> & pointTags,
                             const int tag = -1);

      // cmsh::model::geo::addBSpline
      //
      // Add a cubic b-spline curve in the built-in CAD representation, with
      // `pointTags' control points. If `tag' is positive, set the tag explicitly;
      // otherwise a new tag is selected automatically. Creates a periodic curve if
      // the first and last points are the same. Return the tag of the b-spline
      // curve.
      CMSH_API int addBSpline(const std::vector<int> & pointTags,
                              const int tag = -1);

      // cmsh::model::geo::addBezier
      //
      // Add a Bezier curve in the built-in CAD representation, with `pointTags'
      // control points. If `tag' is positive, set the tag explicitly; otherwise a
      // new tag is selected automatically.  Return the tag of the Bezier curve.
      CMSH_API int addBezier(const std::vector<int> & pointTags,
                             const int tag = -1);

      // cmsh::model::geo::addPolyline
      //
      // Add a polyline curve in the built-in CAD representation, going through the
      // points `pointTags'. If `tag' is positive, set the tag explicitly;
      // otherwise a new tag is selected automatically. Create a periodic curve if
      // the first and last points are the same. Return the tag of the polyline
      // curve.
      CMSH_API int addPolyline(const std::vector<int> & pointTags,
                               const int tag = -1);

      // cmsh::model::geo::addCompoundSpline
      //
      // Add a spline (Catmull-Rom) curve in the built-in CAD representation, going
      // through points sampling the curves in `curveTags'. The density of sampling
      // points on each curve is governed by `numIntervals'. If `tag' is positive,
      // set the tag explicitly; otherwise a new tag is selected automatically.
      // Return the tag of the spline.
      CMSH_API int addCompoundSpline(const std::vector<int> & curveTags,
                                     const int numIntervals = 5,
                                     const int tag = -1);

      // cmsh::model::geo::addCompoundBSpline
      //
      // Add a b-spline curve in the built-in CAD representation, with control
      // points sampling the curves in `curveTags'. The density of sampling points
      // on each curve is governed by `numIntervals'. If `tag' is positive, set the
      // tag explicitly; otherwise a new tag is selected automatically. Return the
      // tag of the b-spline.
      CMSH_API int addCompoundBSpline(const std::vector<int> & curveTags,
                                      const int numIntervals = 20,
                                      const int tag = -1);

      // cmsh::model::geo::addCurveLoop
      //
      // Add a curve loop (a closed wire) in the built-in CAD representation,
      // formed by the curves `curveTags'. `curveTags' should contain (signed) tags
      // of model entities of dimension 1 forming a closed loop: a negative tag
      // signifies that the underlying curve is considered with reversed
      // orientation. If `tag' is positive, set the tag explicitly; otherwise a new
      // tag is selected automatically. If `reorient' is set, automatically
      // reorient the curves if necessary. Return the tag of the curve loop.
      CMSH_API int addCurveLoop(const std::vector<int> & curveTags,
                                const int tag = -1,
                                const bool reorient = false);

      // cmsh::model::geo::addCurveLoops
      //
      // Add curve loops in the built-in CAD representation based on the curves
      // `curveTags'. Return the `tags' of found curve loops, if any.
      CMSH_API void addCurveLoops(const std::vector<int> & curveTags,
                                  std::vector<int> & tags);

      // cmsh::model::geo::addPlaneSurface
      //
      // Add a plane surface in the built-in CAD representation, defined by one or
      // more curve loops `wireTags'. The first curve loop defines the exterior
      // contour; additional curve loop define holes. If `tag' is positive, set the
      // tag explicitly; otherwise a new tag is selected automatically. Return the
      // tag of the surface.
      CMSH_API int addPlaneSurface(const std::vector<int> & wireTags,
                                   const int tag = -1);

      // cmsh::model::geo::addSurfaceFilling
      //
      // Add a surface in the built-in CAD representation, filling the curve loops
      // in `wireTags' using transfinite interpolation. Currently only a single
      // curve loop is supported; this curve loop should be composed by 3 or 4
      // curves only. If `tag' is positive, set the tag explicitly; otherwise a new
      // tag is selected automatically. Return the tag of the surface.
      CMSH_API int addSurfaceFilling(const std::vector<int> & wireTags,
                                     const int tag = -1,
                                     const int sphereCenterTag = -1);

      // cmsh::model::geo::addSurfaceLoop
      //
      // Add a surface loop (a closed shell) formed by `surfaceTags' in the built-
      // in CAD representation.  If `tag' is positive, set the tag explicitly;
      // otherwise a new tag is selected automatically. Return the tag of the
      // shell.
      CMSH_API int addSurfaceLoop(const std::vector<int> & surfaceTags,
                                  const int tag = -1);

      // cmsh::model::geo::addVolume
      //
      // Add a volume (a region) in the built-in CAD representation, defined by one
      // or more shells `shellTags'. The first surface loop defines the exterior
      // boundary; additional surface loop define holes. If `tag' is positive, set
      // the tag explicitly; otherwise a new tag is selected automatically. Return
      // the tag of the volume.
      CMSH_API int addVolume(const std::vector<int> & shellTags,
                             const int tag = -1);

      // cmsh::model::geo::addGeometry
      //
      // Add a `geometry' in the built-in CAD representation. `geometry' can
      // currently be one of "Sphere" or "PolarSphere" (where `numbers' should
      // contain the x, y, z coordinates of the center, followed by the radius), or
      // "Parametric" (where `strings' should contains three expression evaluating
      // to the x, y and z coordinates. If `tag' is positive, set the tag of the
      // geometry explicitly; otherwise a new tag is selected automatically. Return
      // the tag of the geometry.
      CMSH_API int addGeometry(const std::string & geometry,
                               const std::vector<double> & numbers = std::vector<double>(),
                               const std::vector<std::string> & strings = std::vector<std::string>(),
                               const int tag = -1);

      // cmsh::model::geo::addPointOnGeometry
      //
      // Add a point in the built-in CAD representation, at coordinates (`x', `y',
      // `z') on the geometry `geometryTag'. If `meshSize' is > 0, add a meshing
      // constraint at that point. If `tag' is positive, set the tag explicitly;
      // otherwise a new tag is selected automatically. Return the tag of the
      // point. For surface geometries, only the `x' and `y' coordinates are used.
      CMSH_API int addPointOnGeometry(const int geometryTag,
                                      const double x,
                                      const double y,
                                      const double z = 0.,
                                      const double meshSize = 0.,
                                      const int tag = -1);

      // cmsh::model::geo::extrude
      //
      // Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the built-in CAD representation, using a translation along (`dx', `dy',
      // `dz'). Return extruded entities in `outDimTags'. If the `numElements'
      // vector is not empty, also extrude the mesh: the entries in `numElements'
      // give the number of elements in each layer. If the `height' vector is not
      // empty, it provides the (cumulative) height of the different layers,
      // normalized to 1. If `recombine' is set, recombine the mesh in the layers.
      CMSH_API void extrude(const cmsh::vectorpair & dimTags,
                            const double dx,
                            const double dy,
                            const double dz,
                            cmsh::vectorpair & outDimTags,
                            const std::vector<int> & numElements = std::vector<int>(),
                            const std::vector<double> & heights = std::vector<double>(),
                            const bool recombine = false);

      // cmsh::model::geo::revolve
      //
      // Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the built-in CAD representation, using a rotation of `angle' radians
      // around the axis of revolution defined by the point (`x', `y', `z') and the
      // direction (`ax', `ay', `az'). The angle should be strictly smaller than
      // Pi. Return extruded entities in `outDimTags'. If the `numElements' vector
      // is not empty, also extrude the mesh: the entries in `numElements' give the
      // number of elements in each layer. If the `height' vector is not empty, it
      // provides the (cumulative) height of the different layers, normalized to 1.
      // If `recombine' is set, recombine the mesh in the layers.
      CMSH_API void revolve(const cmsh::vectorpair & dimTags,
                            const double x,
                            const double y,
                            const double z,
                            const double ax,
                            const double ay,
                            const double az,
                            const double angle,
                            cmsh::vectorpair & outDimTags,
                            const std::vector<int> & numElements = std::vector<int>(),
                            const std::vector<double> & heights = std::vector<double>(),
                            const bool recombine = false);

      // cmsh::model::geo::twist
      //
      // Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the built-in CAD representation, using a combined translation and rotation
      // of `angle' radians, along (`dx', `dy', `dz') and around the axis of
      // revolution defined by the point (`x', `y', `z') and the direction (`ax',
      // `ay', `az'). The angle should be strictly smaller than Pi. Return extruded
      // entities in `outDimTags'. If the `numElements' vector is not empty, also
      // extrude the mesh: the entries in `numElements' give the number of elements
      // in each layer. If the `height' vector is not empty, it provides the
      // (cumulative) height of the different layers, normalized to 1. If
      // `recombine' is set, recombine the mesh in the layers.
      CMSH_API void twist(const cmsh::vectorpair & dimTags,
                          const double x,
                          const double y,
                          const double z,
                          const double dx,
                          const double dy,
                          const double dz,
                          const double ax,
                          const double ay,
                          const double az,
                          const double angle,
                          cmsh::vectorpair & outDimTags,
                          const std::vector<int> & numElements = std::vector<int>(),
                          const std::vector<double> & heights = std::vector<double>(),
                          const bool recombine = false);

      // cmsh::model::geo::extrudeBoundaryLayer
      //
      // Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the built-in CAD representation along the normals of the mesh, creating
      // discrete boundary layer entities. Return extruded entities in
      // `outDimTags'. The entries in `numElements' give the number of elements in
      // each layer. If the `height' vector is not empty, it provides the
      // (cumulative) height of the different layers. If `recombine' is set,
      // recombine the mesh in the layers. A second boundary layer can be created
      // from the same entities if `second' is set. If `viewIndex' is >= 0, use the
      // corresponding view to either specify the normals (if the view contains a
      // vector field) or scale the normals (if the view is scalar).
      CMSH_API void extrudeBoundaryLayer(const cmsh::vectorpair & dimTags,
                                         cmsh::vectorpair & outDimTags,
                                         const std::vector<int> & numElements = std::vector<int>(1, 1),
                                         const std::vector<double> & heights = std::vector<double>(),
                                         const bool recombine = false,
                                         const bool second = false,
                                         const int viewIndex = -1);

      // cmsh::model::geo::translate
      //
      // Translate the entities `dimTags' (given as a vector of (dim, tag) pairs)
      // in the built-in CAD representation along (`dx', `dy', `dz').
      CMSH_API void translate(const cmsh::vectorpair & dimTags,
                              const double dx,
                              const double dy,
                              const double dz);

      // cmsh::model::geo::rotate
      //
      // Rotate the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the built-in CAD representation by `angle' radians around the axis of
      // revolution defined by the point (`x', `y', `z') and the direction (`ax',
      // `ay', `az').
      CMSH_API void rotate(const cmsh::vectorpair & dimTags,
                           const double x,
                           const double y,
                           const double z,
                           const double ax,
                           const double ay,
                           const double az,
                           const double angle);

      // cmsh::model::geo::dilate
      //
      // Scale the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the built-in CAD representation by factors `a', `b' and `c' along the
      // three coordinate axes; use (`x', `y', `z') as the center of the homothetic
      // transformation.
      CMSH_API void dilate(const cmsh::vectorpair & dimTags,
                           const double x,
                           const double y,
                           const double z,
                           const double a,
                           const double b,
                           const double c);

      // cmsh::model::geo::mirror
      //
      // Mirror the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the built-in CAD representation, with respect to the plane of equation `a'
      // * x + `b' * y + `c' * z + `d' = 0.
      CMSH_API void mirror(const cmsh::vectorpair & dimTags,
                           const double a,
                           const double b,
                           const double c,
                           const double d);

      // cmsh::model::geo::symmetrize
      //
      // Mirror the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the built-in CAD representation, with respect to the plane of equation `a'
      // * x + `b' * y + `c' * z + `d' = 0. (This is a synonym for `mirror', which
      // will be deprecated in a future release.)
      CMSH_API void symmetrize(const cmsh::vectorpair & dimTags,
                               const double a,
                               const double b,
                               const double c,
                               const double d);

      // cmsh::model::geo::copy
      //
      // Copy the entities `dimTags' (given as a vector of (dim, tag) pairs) in the
      // built-in CAD representation; the new entities are returned in
      // `outDimTags'.
      CMSH_API void copy(const cmsh::vectorpair & dimTags,
                         cmsh::vectorpair & outDimTags);

      // cmsh::model::geo::remove
      //
      // Remove the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the built-in CAD representation, provided that they are not on the
      // boundary of higher-dimensional entities. If `recursive' is true, remove
      // all the entities on their boundaries, down to dimension 0.
      CMSH_API void remove(const cmsh::vectorpair & dimTags,
                           const bool recursive = false);

      // cmsh::model::geo::removeAllDuplicates
      //
      // Remove all duplicate entities in the built-in CAD representation
      // (different entities at the same geometrical location).
      CMSH_API void removeAllDuplicates();

      // cmsh::model::geo::splitCurve
      //
      // Split the curve of tag `tag' in the built-in CAD representation, on the
      // specified control points `pointTags'. This feature is only available for
      // lines, splines and b-splines. Return the tag(s) `curveTags' of the newly
      // created curve(s).
      CMSH_API void splitCurve(const int tag,
                               const std::vector<int> & pointTags,
                               std::vector<int> & curveTags);

      // cmsh::model::geo::getMaxTag
      //
      // Get the maximum tag of entities of dimension `dim' in the built-in CAD
      // representation.
      CMSH_API int getMaxTag(const int dim);

      // cmsh::model::geo::setMaxTag
      //
      // Set the maximum tag `maxTag' for entities of dimension `dim' in the built-
      // in CAD representation.
      CMSH_API void setMaxTag(const int dim,
                              const int maxTag);

      // cmsh::model::geo::addPhysicalGroup
      //
      // Add a physical group of dimension `dim', grouping the entities with tags
      // `tags' in the built-in CAD representation. Return the tag of the physical
      // group, equal to `tag' if `tag' is positive, or a new tag if `tag' < 0. Set
      // the name of the physical group if `name' is not empty.
      CMSH_API int addPhysicalGroup(const int dim,
                                    const std::vector<int> & tags,
                                    const int tag = -1,
                                    const std::string & name = "");

      // cmsh::model::geo::removePhysicalGroups
      //
      // Remove the physical groups `dimTags' (given as a vector of (dim, tag)
      // pairs) from the built-in CAD representation. If `dimTags' is empty, remove
      // all groups.
      CMSH_API void removePhysicalGroups(const cmsh::vectorpair & dimTags = cmsh::vectorpair());

      // cmsh::model::geo::synchronize
      //
      // Synchronize the built-in CAD representation with the current Gmsh model.
      // This can be called at any time, but since it involves a non trivial amount
      // of processing, the number of synchronization points should normally be
      // minimized. Without synchronization the entities in the built-in CAD
      // representation are not available to any function outside of the built-in
      // CAD kernel functions.
      CMSH_API void synchronize();

      namespace mesh { // Built-in CAD kernel meshing constraints

        // cmsh::model::geo::mesh::setSize
        //
        // Set a mesh size constraint on the entities `dimTags' (given as a vector
        // of (dim, tag) pairs) in the built-in CAD kernel representation.
        // Currently only entities of dimension 0 (points) are handled.
        CMSH_API void setSize(const cmsh::vectorpair & dimTags,
                              const double size);

        // cmsh::model::geo::mesh::setTransfiniteCurve
        //
        // Set a transfinite meshing constraint on the curve `tag' in the built-in
        // CAD kernel representation, with `numNodes' nodes distributed according
        // to `meshType' and `coef'. Currently supported types are "Progression"
        // (geometrical progression with power `coef') and "Bump" (refinement
        // toward both extremities of the curve).
        CMSH_API void setTransfiniteCurve(const int tag,
                                          const int nPoints,
                                          const std::string & meshType = "Progression",
                                          const double coef = 1.);

        // cmsh::model::geo::mesh::setTransfiniteSurface
        //
        // Set a transfinite meshing constraint on the surface `tag' in the built-
        // in CAD kernel representation. `arrangement' describes the arrangement of
        // the triangles when the surface is not flagged as recombined: currently
        // supported values are "Left", "Right", "AlternateLeft" and
        // "AlternateRight". `cornerTags' can be used to specify the (3 or 4)
        // corners of the transfinite interpolation explicitly; specifying the
        // corners explicitly is mandatory if the surface has more that 3 or 4
        // points on its boundary.
        CMSH_API void setTransfiniteSurface(const int tag,
                                            const std::string & arrangement = "Left",
                                            const std::vector<int> & cornerTags = std::vector<int>());

        // cmsh::model::geo::mesh::setTransfiniteVolume
        //
        // Set a transfinite meshing constraint on the surface `tag' in the built-
        // in CAD kernel representation. `cornerTags' can be used to specify the (6
        // or 8) corners of the transfinite interpolation explicitly.
        CMSH_API void setTransfiniteVolume(const int tag,
                                           const std::vector<int> & cornerTags = std::vector<int>());

        // cmsh::model::geo::mesh::setRecombine
        //
        // Set a recombination meshing constraint on the entity of dimension `dim'
        // and tag `tag' in the built-in CAD kernel representation. Currently only
        // entities of dimension 2 (to recombine triangles into quadrangles) are
        // supported; `angle' specifies the threshold angle for the simple
        // recombination algorithm.
        CMSH_API void setRecombine(const int dim,
                                   const int tag,
                                   const double angle = 45.);

        // cmsh::model::geo::mesh::setSmoothing
        //
        // Set a smoothing meshing constraint on the entity of dimension `dim' and
        // tag `tag' in the built-in CAD kernel representation. `val' iterations of
        // a Laplace smoother are applied.
        CMSH_API void setSmoothing(const int dim,
                                   const int tag,
                                   const int val);

        // cmsh::model::geo::mesh::setReverse
        //
        // Set a reverse meshing constraint on the entity of dimension `dim' and
        // tag `tag' in the built-in CAD kernel representation. If `val' is true,
        // the mesh orientation will be reversed with respect to the natural mesh
        // orientation (i.e. the orientation consistent with the orientation of the
        // geometry). If `val' is false, the mesh is left as-is.
        CMSH_API void setReverse(const int dim,
                                 const int tag,
                                 const bool val = true);

        // cmsh::model::geo::mesh::setAlgorithm
        //
        // Set the meshing algorithm on the entity of dimension `dim' and tag `tag'
        // in the built-in CAD kernel representation. Currently only supported for
        // `dim' == 2.
        CMSH_API void setAlgorithm(const int dim,
                                   const int tag,
                                   const int val);

        // cmsh::model::geo::mesh::setSizeFromBoundary
        //
        // Force the mesh size to be extended from the boundary, or not, for the
        // entity of dimension `dim' and tag `tag' in the built-in CAD kernel
        // representation. Currently only supported for `dim' == 2.
        CMSH_API void setSizeFromBoundary(const int dim,
                                          const int tag,
                                          const int val);

      } // namespace mesh

    } // namespace geo

    namespace occ { // OpenCASCADE CAD kernel functions

      // cmsh::model::occ::addPoint
      //
      // Add a geometrical point in the OpenCASCADE CAD representation, at
      // coordinates (`x', `y', `z'). If `meshSize' is > 0, add a meshing
      // constraint at that point. If `tag' is positive, set the tag explicitly;
      // otherwise a new tag is selected automatically. Return the tag of the
      // point. (Note that the point will be added in the current model only after
      // `synchronize' is called. This behavior holds for all the entities added in
      // the occ module.)
      CMSH_API int addPoint(const double x,
                            const double y,
                            const double z,
                            const double meshSize = 0.,
                            const int tag = -1);

      // cmsh::model::occ::addLine
      //
      // Add a straight line segment in the OpenCASCADE CAD representation, between
      // the two points with tags `startTag' and `endTag'. If `tag' is positive,
      // set the tag explicitly; otherwise a new tag is selected automatically.
      // Return the tag of the line.
      CMSH_API int addLine(const int startTag,
                           const int endTag,
                           const int tag = -1);

      // cmsh::model::occ::addCircleArc
      //
      // Add a circle arc in the OpenCASCADE CAD representation, between the two
      // points with tags `startTag' and `endTag', with middle point `middleTag'.
      // If `center' is true, the middle point is the center of the circle;
      // otherwise the circle goes through the middle point. If `tag' is positive,
      // set the tag explicitly; otherwise a new tag is selected automatically.
      // Return the tag of the circle arc.
      CMSH_API int addCircleArc(const int startTag,
                                const int middleTag,
                                const int endTag,
                                const int tag = -1,
                                const bool center = true);

      // cmsh::model::occ::addCircle
      //
      // Add a circle of center (`x', `y', `z') and radius `r' in the OpenCASCADE
      // CAD representation. If `tag' is positive, set the tag explicitly;
      // otherwise a new tag is selected automatically. If `angle1' and `angle2'
      // are specified, create a circle arc between the two angles. If a vector
      // `zAxis' of size 3 is provided, use it as the normal to the circle plane
      // (z-axis). If a vector `xAxis' of size 3 is provided in addition to
      // `zAxis', use it to define the x-axis. Return the tag of the circle.
      CMSH_API int addCircle(const double x,
                             const double y,
                             const double z,
                             const double r,
                             const int tag = -1,
                             const double angle1 = 0.,
                             const double angle2 = 2*M_PI,
                             const std::vector<double> & zAxis = std::vector<double>(),
                             const std::vector<double> & xAxis = std::vector<double>());

      // cmsh::model::occ::addEllipseArc
      //
      // Add an ellipse arc in the OpenCASCADE CAD representation, between the two
      // points `startTag' and `endTag', and with center `centerTag' and major axis
      // point `majorTag'. If `tag' is positive, set the tag explicitly; otherwise
      // a new tag is selected automatically. Return the tag of the ellipse arc.
      // Note that OpenCASCADE does not allow creating ellipse arcs with the major
      // radius smaller than the minor radius.
      CMSH_API int addEllipseArc(const int startTag,
                                 const int centerTag,
                                 const int majorTag,
                                 const int endTag,
                                 const int tag = -1);

      // cmsh::model::occ::addEllipse
      //
      // Add an ellipse of center (`x', `y', `z') and radii `r1' and `r2' (with
      // `r1' >= `r2') along the x- and y-axes, respectively, in the OpenCASCADE
      // CAD representation. If `tag' is positive, set the tag explicitly;
      // otherwise a new tag is selected automatically. If `angle1' and `angle2'
      // are specified, create an ellipse arc between the two angles. If a vector
      // `zAxis' of size 3 is provided, use it as the normal to the ellipse plane
      // (z-axis). If a vector `xAxis' of size 3 is provided in addition to
      // `zAxis', use it to define the x-axis. Return the tag of the ellipse.
      CMSH_API int addEllipse(const double x,
                              const double y,
                              const double z,
                              const double r1,
                              const double r2,
                              const int tag = -1,
                              const double angle1 = 0.,
                              const double angle2 = 2*M_PI,
                              const std::vector<double> & zAxis = std::vector<double>(),
                              const std::vector<double> & xAxis = std::vector<double>());

      // cmsh::model::occ::addSpline
      //
      // Add a spline (C2 b-spline) curve in the OpenCASCADE CAD representation,
      // going through the points `pointTags'. If `tag' is positive, set the tag
      // explicitly; otherwise a new tag is selected automatically. Create a
      // periodic curve if the first and last points are the same. Return the tag
      // of the spline curve. If the `tangents' vector contains 6 entries, use them
      // as concatenated x, y, z components of the initial and final tangents of
      // the b-spline; if it contains 3 times as many entries as the number of
      // points, use them as concatenated x, y, z components of the tangents at
      // each point, unless the norm of the tangent is zero.
      CMSH_API int addSpline(const std::vector<int> & pointTags,
                             const int tag = -1,
                             const std::vector<double> & tangents = std::vector<double>());

      // cmsh::model::occ::addBSpline
      //
      // Add a b-spline curve of degree `degree' in the OpenCASCADE CAD
      // representation, with `pointTags' control points. If `weights', `knots' or
      // `multiplicities' are not provided, default parameters are computed
      // automatically. If `tag' is positive, set the tag explicitly; otherwise a
      // new tag is selected automatically. Create a periodic curve if the first
      // and last points are the same. Return the tag of the b-spline curve.
      CMSH_API int addBSpline(const std::vector<int> & pointTags,
                              const int tag = -1,
                              const int degree = 3,
                              const std::vector<double> & weights = std::vector<double>(),
                              const std::vector<double> & knots = std::vector<double>(),
                              const std::vector<int> & multiplicities = std::vector<int>());

      // cmsh::model::occ::addBezier
      //
      // Add a Bezier curve in the OpenCASCADE CAD representation, with `pointTags'
      // control points. If `tag' is positive, set the tag explicitly; otherwise a
      // new tag is selected automatically. Return the tag of the Bezier curve.
      CMSH_API int addBezier(const std::vector<int> & pointTags,
                             const int tag = -1);

      // cmsh::model::occ::addWire
      //
      // Add a wire (open or closed) in the OpenCASCADE CAD representation, formed
      // by the curves `curveTags'. Note that an OpenCASCADE wire can be made of
      // curves that share geometrically identical (but topologically different)
      // points. If `tag' is positive, set the tag explicitly; otherwise a new tag
      // is selected automatically. Return the tag of the wire.
      CMSH_API int addWire(const std::vector<int> & curveTags,
                           const int tag = -1,
                           const bool checkClosed = false);

      // cmsh::model::occ::addCurveLoop
      //
      // Add a curve loop (a closed wire) in the OpenCASCADE CAD representation,
      // formed by the curves `curveTags'. `curveTags' should contain tags of
      // curves forming a closed loop. Negative tags can be specified for
      // compatibility with the built-in kernel, but are simply ignored: the wire
      // is oriented according to the orientation of its first curve. Note that an
      // OpenCASCADE curve loop can be made of curves that share geometrically
      // identical (but topologically different) points. If `tag' is positive, set
      // the tag explicitly; otherwise a new tag is selected automatically. Return
      // the tag of the curve loop.
      CMSH_API int addCurveLoop(const std::vector<int> & curveTags,
                                const int tag = -1);

      // cmsh::model::occ::addRectangle
      //
      // Add a rectangle in the OpenCASCADE CAD representation, with lower left
      // corner at (`x', `y', `z') and upper right corner at (`x' + `dx', `y' +
      // `dy', `z'). If `tag' is positive, set the tag explicitly; otherwise a new
      // tag is selected automatically. Round the corners if `roundedRadius' is
      // nonzero. Return the tag of the rectangle.
      CMSH_API int addRectangle(const double x,
                                const double y,
                                const double z,
                                const double dx,
                                const double dy,
                                const int tag = -1,
                                const double roundedRadius = 0.);

      // cmsh::model::occ::addDisk
      //
      // Add a disk in the OpenCASCADE CAD representation, with center (`xc', `yc',
      // `zc') and radius `rx' along the x-axis and `ry' along the y-axis (`rx' >=
      // `ry'). If `tag' is positive, set the tag explicitly; otherwise a new tag
      // is selected automatically. If a vector `zAxis' of size 3 is provided, use
      // it as the normal to the disk (z-axis). If a vector `xAxis' of size 3 is
      // provided in addition to `zAxis', use it to define the x-axis. Return the
      // tag of the disk.
      CMSH_API int addDisk(const double xc,
                           const double yc,
                           const double zc,
                           const double rx,
                           const double ry,
                           const int tag = -1,
                           const std::vector<double> & zAxis = std::vector<double>(),
                           const std::vector<double> & xAxis = std::vector<double>());

      // cmsh::model::occ::addPlaneSurface
      //
      // Add a plane surface in the OpenCASCADE CAD representation, defined by one
      // or more curve loops (or closed wires) `wireTags'. The first curve loop
      // defines the exterior contour; additional curve loop define holes. If `tag'
      // is positive, set the tag explicitly; otherwise a new tag is selected
      // automatically. Return the tag of the surface.
      CMSH_API int addPlaneSurface(const std::vector<int> & wireTags,
                                   const int tag = -1);

      // cmsh::model::occ::addSurfaceFilling
      //
      // Add a surface in the OpenCASCADE CAD representation, filling the curve
      // loop `wireTag'. If `tag' is positive, set the tag explicitly; otherwise a
      // new tag is selected automatically. Return the tag of the surface. If
      // `pointTags' are provided, force the surface to pass through the given
      // points. The other optional arguments are `degree' (the degree of the
      // energy criterion to minimize for computing the deformation of the
      // surface), `numPointsOnCurves' (the average number of points for
      // discretisation of the bounding curves), `numIter' (the maximum number of
      // iterations of the optimization process), `anisotropic' (improve
      // performance when the ratio of the length along the two parametric
      // coordinates of the surface is high), `tol2d' (tolerance to the constraints
      // in the parametric plane of the surface), `tol3d' (the maximum distance
      // allowed between the support surface and the constraints), `tolAng' (the
      // maximum angle allowed between the normal of the surface and the
      // constraints), `tolCurv' (the maximum difference of curvature allowed
      // between the surface and the constraint), `maxDegree' (the highest degree
      // which the polynomial defining the filling surface can have) and,
      // `maxSegments' (the largest number of segments which the filling surface
      // can have).
      CMSH_API int addSurfaceFilling(const int wireTag,
                                     const int tag = -1,
                                     const std::vector<int> & pointTags = std::vector<int>(),
                                     const int degree = 2,
                                     const int numPointsOnCurves = 15,
                                     const int numIter = 2,
                                     const bool anisotropic = false,
                                     const double tol2d = 0.00001,
                                     const double tol3d = 0.0001,
                                     const double tolAng = 0.01,
                                     const double tolCurv = 0.1,
                                     const int maxDegree = 8,
                                     const int maxSegments = 9);

      // cmsh::model::occ::addBSplineFilling
      //
      // Add a BSpline surface in the OpenCASCADE CAD representation, filling the
      // curve loop `wireTag'. The curve loop should be made of 2, 3 or 4 curves.
      // The optional `type' argument specifies the type of filling: "Stretch"
      // creates the flattest patch, "Curved" (the default) creates the most
      // rounded patch, and "Coons" creates a rounded patch with less depth than
      // "Curved". If `tag' is positive, set the tag explicitly; otherwise a new
      // tag is selected automatically. Return the tag of the surface.
      CMSH_API int addBSplineFilling(const int wireTag,
                                     const int tag = -1,
                                     const std::string & type = "");

      // cmsh::model::occ::addBezierFilling
      //
      // Add a Bezier surface in the OpenCASCADE CAD representation, filling the
      // curve loop `wireTag'. The curve loop should be made of 2, 3 or 4 Bezier
      // curves. The optional `type' argument specifies the type of filling:
      // "Stretch" creates the flattest patch, "Curved" (the default) creates the
      // most rounded patch, and "Coons" creates a rounded patch with less depth
      // than "Curved". If `tag' is positive, set the tag explicitly; otherwise a
      // new tag is selected automatically. Return the tag of the surface.
      CMSH_API int addBezierFilling(const int wireTag,
                                    const int tag = -1,
                                    const std::string & type = "");

      // cmsh::model::occ::addBSplineSurface
      //
      // Add a b-spline surface of degree `degreeU' x `degreeV' in the OpenCASCADE
      // CAD representation, with `pointTags' control points given as a single
      // vector [Pu1v1, ... Pu`numPointsU'v1, Pu1v2, ...]. If `weights', `knotsU',
      // `knotsV', `multiplicitiesU' or `multiplicitiesV' are not provided, default
      // parameters are computed automatically. If `tag' is positive, set the tag
      // explicitly; otherwise a new tag is selected automatically. If `wireTags'
      // is provided, trim the b-spline patch using the provided wires: the first
      // wire defines the external contour, the others define holes. If `wire3D' is
      // set, consider wire curves as 3D curves and project them on the b-spline
      // surface; otherwise consider the wire curves as defined in the parametric
      // space of the surface. Return the tag of the b-spline surface.
      CMSH_API int addBSplineSurface(const std::vector<int> & pointTags,
                                     const int numPointsU,
                                     const int tag = -1,
                                     const int degreeU = 3,
                                     const int degreeV = 3,
                                     const std::vector<double> & weights = std::vector<double>(),
                                     const std::vector<double> & knotsU = std::vector<double>(),
                                     const std::vector<double> & knotsV = std::vector<double>(),
                                     const std::vector<int> & multiplicitiesU = std::vector<int>(),
                                     const std::vector<int> & multiplicitiesV = std::vector<int>(),
                                     const std::vector<int> & wireTags = std::vector<int>(),
                                     const bool wire3D = false);

      // cmsh::model::occ::addBezierSurface
      //
      // Add a Bezier surface in the OpenCASCADE CAD representation, with
      // `pointTags' control points given as a single vector [Pu1v1, ...
      // Pu`numPointsU'v1, Pu1v2, ...]. If `tag' is positive, set the tag
      // explicitly; otherwise a new tag is selected automatically. If `wireTags'
      // is provided, trim the Bezier patch using the provided wires: the first
      // wire defines the external contour, the others define holes. If `wire3D' is
      // set, consider wire curves as 3D curves and project them on the Bezier
      // surface; otherwise consider the wire curves as defined in the parametric
      // space of the surface. Return the tag of the Bezier surface.
      CMSH_API int addBezierSurface(const std::vector<int> & pointTags,
                                    const int numPointsU,
                                    const int tag = -1,
                                    const std::vector<int> & wireTags = std::vector<int>(),
                                    const bool wire3D = false);

      // cmsh::model::occ::addTrimmedSurface
      //
      // Trim the surface `surfaceTag' with the wires `wireTags', replacing any
      // existing trimming curves. The first wire defines the external contour, the
      // others define holes. If `wire3D' is set, consider wire curves as 3D curves
      // and project them on the surface; otherwise consider the wire curves as
      // defined in the parametric space of the surface. If `tag' is positive, set
      // the tag explicitly; otherwise a new tag is selected automatically. Return
      // the tag of the trimmed surface.
      CMSH_API int addTrimmedSurface(const int surfaceTag,
                                     const std::vector<int> & wireTags = std::vector<int>(),
                                     const bool wire3D = false,
                                     const int tag = -1);

      // cmsh::model::occ::addSurfaceLoop
      //
      // Add a surface loop (a closed shell) in the OpenCASCADE CAD representation,
      // formed by `surfaceTags'.  If `tag' is positive, set the tag explicitly;
      // otherwise a new tag is selected automatically. Return the tag of the
      // surface loop. Setting `sewing' allows one to build a shell made of
      // surfaces that share geometrically identical (but topologically different)
      // curves.
      CMSH_API int addSurfaceLoop(const std::vector<int> & surfaceTags,
                                  const int tag = -1,
                                  const bool sewing = false);

      // cmsh::model::occ::addVolume
      //
      // Add a volume (a region) in the OpenCASCADE CAD representation, defined by
      // one or more surface loops `shellTags'. The first surface loop defines the
      // exterior boundary; additional surface loop define holes. If `tag' is
      // positive, set the tag explicitly; otherwise a new tag is selected
      // automatically. Return the tag of the volume.
      CMSH_API int addVolume(const std::vector<int> & shellTags,
                             const int tag = -1);

      // cmsh::model::occ::addSphere
      //
      // Add a sphere of center (`xc', `yc', `zc') and radius `r' in the
      // OpenCASCADE CAD representation. The optional `angle1' and `angle2'
      // arguments define the polar angle opening (from -Pi/2 to Pi/2). The
      // optional `angle3' argument defines the azimuthal opening (from 0 to 2*Pi).
      // If `tag' is positive, set the tag explicitly; otherwise a new tag is
      // selected automatically. Return the tag of the sphere.
      CMSH_API int addSphere(const double xc,
                             const double yc,
                             const double zc,
                             const double radius,
                             const int tag = -1,
                             const double angle1 = -M_PI/2,
                             const double angle2 = M_PI/2,
                             const double angle3 = 2*M_PI);

      // cmsh::model::occ::addBox
      //
      // Add a parallelepipedic box in the OpenCASCADE CAD representation, defined
      // by a point (`x', `y', `z') and the extents along the x-, y- and z-axes. If
      // `tag' is positive, set the tag explicitly; otherwise a new tag is selected
      // automatically. Return the tag of the box.
      CMSH_API int addBox(const double x,
                          const double y,
                          const double z,
                          const double dx,
                          const double dy,
                          const double dz,
                          const int tag = -1);

      // cmsh::model::occ::addCylinder
      //
      // Add a cylinder in the OpenCASCADE CAD representation, defined by the
      // center (`x', `y', `z') of its first circular face, the 3 components (`dx',
      // `dy', `dz') of the vector defining its axis and its radius `r'. The
      // optional `angle' argument defines the angular opening (from 0 to 2*Pi). If
      // `tag' is positive, set the tag explicitly; otherwise a new tag is selected
      // automatically. Return the tag of the cylinder.
      CMSH_API int addCylinder(const double x,
                               const double y,
                               const double z,
                               const double dx,
                               const double dy,
                               const double dz,
                               const double r,
                               const int tag = -1,
                               const double angle = 2*M_PI);

      // cmsh::model::occ::addCone
      //
      // Add a cone in the OpenCASCADE CAD representation, defined by the center
      // (`x', `y', `z') of its first circular face, the 3 components of the vector
      // (`dx', `dy', `dz') defining its axis and the two radii `r1' and `r2' of
      // the faces (these radii can be zero). If `tag' is positive, set the tag
      // explicitly; otherwise a new tag is selected automatically. `angle' defines
      // the optional angular opening (from 0 to 2*Pi). Return the tag of the cone.
      CMSH_API int addCone(const double x,
                           const double y,
                           const double z,
                           const double dx,
                           const double dy,
                           const double dz,
                           const double r1,
                           const double r2,
                           const int tag = -1,
                           const double angle = 2*M_PI);

      // cmsh::model::occ::addWedge
      //
      // Add a right angular wedge in the OpenCASCADE CAD representation, defined
      // by the right-angle point (`x', `y', `z') and the 3 extends along the x-,
      // y- and z-axes (`dx', `dy', `dz'). If `tag' is positive, set the tag
      // explicitly; otherwise a new tag is selected automatically. The optional
      // argument `ltx' defines the top extent along the x-axis. If a vector
      // `zAxis' of size 3 is provided, use it to define the z-axis. Return the tag
      // of the wedge.
      CMSH_API int addWedge(const double x,
                            const double y,
                            const double z,
                            const double dx,
                            const double dy,
                            const double dz,
                            const int tag = -1,
                            const double ltx = 0.,
                            const std::vector<double> & zAxis = std::vector<double>());

      // cmsh::model::occ::addTorus
      //
      // Add a torus in the OpenCASCADE CAD representation, defined by its center
      // (`x', `y', `z') and its 2 radii `r' and `r2'. If `tag' is positive, set
      // the tag explicitly; otherwise a new tag is selected automatically. The
      // optional argument `angle' defines the angular opening (from 0 to 2*Pi). If
      // a vector `zAxis' of size 3 is provided, use it to define the z-axis.
      // Return the tag of the torus.
      CMSH_API int addTorus(const double x,
                            const double y,
                            const double z,
                            const double r1,
                            const double r2,
                            const int tag = -1,
                            const double angle = 2*M_PI,
                            const std::vector<double> & zAxis = std::vector<double>());

      // cmsh::model::occ::addThruSections
      //
      // Add a volume (if the optional argument `makeSolid' is set) or surfaces in
      // the OpenCASCADE CAD representation, defined through the open or closed
      // wires `wireTags'. If `tag' is positive, set the tag explicitly; otherwise
      // a new tag is selected automatically. The new entities are returned in
      // `outDimTags' as a vector of (dim, tag) pairs. If the optional argument
      // `makeRuled' is set, the surfaces created on the boundary are forced to be
      // ruled surfaces. If `maxDegree' is positive, set the maximal degree of
      // resulting surface. The optional argument `continuity' allows to specify
      // the continuity of the resulting shape ("C0", "G1", "C1", "G2", "C2", "C3",
      // "CN"). The optional argument `parametrization' sets the parametrization
      // type ("ChordLength", "Centripetal", "IsoParametric"). The optional
      // argument `smoothing' determines if smoothing is applied.
      CMSH_API void addThruSections(const std::vector<int> & wireTags,
                                    cmsh::vectorpair & outDimTags,
                                    const int tag = -1,
                                    const bool makeSolid = true,
                                    const bool makeRuled = false,
                                    const int maxDegree = -1,
                                    const std::string & continuity = "",
                                    const std::string & parametrization = "",
                                    const bool smoothing = false);

      // cmsh::model::occ::addThickSolid
      //
      // Add a hollowed volume in the OpenCASCADE CAD representation, built from an
      // initial volume `volumeTag' and a set of faces from this volume
      // `excludeSurfaceTags', which are to be removed. The remaining faces of the
      // volume become the walls of the hollowed solid, with thickness `offset'. If
      // `tag' is positive, set the tag explicitly; otherwise a new tag is selected
      // automatically.
      CMSH_API void addThickSolid(const int volumeTag,
                                  const std::vector<int> & excludeSurfaceTags,
                                  const double offset,
                                  cmsh::vectorpair & outDimTags,
                                  const int tag = -1);

      // cmsh::model::occ::extrude
      //
      // Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the OpenCASCADE CAD representation, using a translation along (`dx', `dy',
      // `dz'). Return extruded entities in `outDimTags'. If the `numElements'
      // vector is not empty, also extrude the mesh: the entries in `numElements'
      // give the number of elements in each layer. If the `height' vector is not
      // empty, it provides the (cumulative) height of the different layers,
      // normalized to 1. If `recombine' is set, recombine the mesh in the layers.
      CMSH_API void extrude(const cmsh::vectorpair & dimTags,
                            const double dx,
                            const double dy,
                            const double dz,
                            cmsh::vectorpair & outDimTags,
                            const std::vector<int> & numElements = std::vector<int>(),
                            const std::vector<double> & heights = std::vector<double>(),
                            const bool recombine = false);

      // cmsh::model::occ::revolve
      //
      // Extrude the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the OpenCASCADE CAD representation, using a rotation of `angle' radians
      // around the axis of revolution defined by the point (`x', `y', `z') and the
      // direction (`ax', `ay', `az'). Return extruded entities in `outDimTags'. If
      // the `numElements' vector is not empty, also extrude the mesh: the entries
      // in `numElements' give the number of elements in each layer. If the
      // `height' vector is not empty, it provides the (cumulative) height of the
      // different layers, normalized to 1. When the mesh is extruded the angle
      // should be strictly smaller than 2*Pi. If `recombine' is set, recombine the
      // mesh in the layers.
      CMSH_API void revolve(const cmsh::vectorpair & dimTags,
                            const double x,
                            const double y,
                            const double z,
                            const double ax,
                            const double ay,
                            const double az,
                            const double angle,
                            cmsh::vectorpair & outDimTags,
                            const std::vector<int> & numElements = std::vector<int>(),
                            const std::vector<double> & heights = std::vector<double>(),
                            const bool recombine = false);

      // cmsh::model::occ::addPipe
      //
      // Add a pipe in the OpenCASCADE CAD representation, by extruding the
      // entities `dimTags' (given as a vector of (dim, tag) pairs) along the wire
      // `wireTag'. The type of sweep can be specified with `trihedron' (possible
      // values: "DiscreteTrihedron", "CorrectedFrenet", "Fixed", "Frenet",
      // "ConstantNormal", "Darboux", "GuideAC", "GuidePlan", "GuideACWithContact",
      // "GuidePlanWithContact"). If `trihedron' is not provided,
      // "DiscreteTrihedron" is assumed. Return the pipe in `outDimTags'.
      CMSH_API void addPipe(const cmsh::vectorpair & dimTags,
                            const int wireTag,
                            cmsh::vectorpair & outDimTags,
                            const std::string & trihedron = "");

      // cmsh::model::occ::fillet
      //
      // Fillet the volumes `volumeTags' on the curves `curveTags' with radii
      // `radii'. The `radii' vector can either contain a single radius, as many
      // radii as `curveTags', or twice as many as `curveTags' (in which case
      // different radii are provided for the begin and end points of the curves).
      // Return the filleted entities in `outDimTags' as a vector of (dim, tag)
      // pairs. Remove the original volume if `removeVolume' is set.
      CMSH_API void fillet(const std::vector<int> & volumeTags,
                           const std::vector<int> & curveTags,
                           const std::vector<double> & radii,
                           cmsh::vectorpair & outDimTags,
                           const bool removeVolume = true);

      // cmsh::model::occ::chamfer
      //
      // Chamfer the volumes `volumeTags' on the curves `curveTags' with distances
      // `distances' measured on surfaces `surfaceTags'. The `distances' vector can
      // either contain a single distance, as many distances as `curveTags' and
      // `surfaceTags', or twice as many as `curveTags' and `surfaceTags' (in which
      // case the first in each pair is measured on the corresponding surface in
      // `surfaceTags', the other on the other adjacent surface). Return the
      // chamfered entities in `outDimTags'. Remove the original volume if
      // `removeVolume' is set.
      CMSH_API void chamfer(const std::vector<int> & volumeTags,
                            const std::vector<int> & curveTags,
                            const std::vector<int> & surfaceTags,
                            const std::vector<double> & distances,
                            cmsh::vectorpair & outDimTags,
                            const bool removeVolume = true);

      // cmsh::model::occ::defeature
      //
      // Defeature the volumes `volumeTags' by removing the surfaces `surfaceTags'.
      // Return the defeatured entities in `outDimTags'. Remove the original volume
      // if `removeVolume' is set.
      CMSH_API void defeature(const std::vector<int> & volumeTags,
                              const std::vector<int> & surfaceTags,
                              cmsh::vectorpair & outDimTags,
                              const bool removeVolume = true);

      // cmsh::model::occ::fillet2D
      //
      // Create a fillet edge between edges `edgeTag1' and `edgeTag2' with radius
      // `radius'. The modifed edges keep their tag. If `tag' is positive, set the
      // tag explicitly; otherwise a new tag is selected automatically.
      CMSH_API int fillet2D(const int edgeTag1,
                            const int edgeTag2,
                            const double radius,
                            const int tag = -1);

      // cmsh::model::occ::chamfer2D
      //
      // Create a chamfer edge between edges `edgeTag1' and `edgeTag2' with
      // distance1 `distance1' and distance2 `distance2'. The modifed edges keep
      // their tag. If `tag' is positive, set the tag explicitly; otherwise a new
      // tag is selected automatically.
      CMSH_API int chamfer2D(const int edgeTag1,
                             const int edgeTag2,
                             const double distance1,
                             const double distance2,
                             const int tag = -1);

      // cmsh::model::occ::offsetCurve
      //
      // Create an offset curve based on the curve loop `curveLoopTag' with offset
      // `offset'. Return the offset curves in `outDimTags' as a vector of (dim,
      // tag) pairs.
      CMSH_API void offsetCurve(const int curveLoopTag,
                                const double offset,
                                cmsh::vectorpair & outDimTags);

      // cmsh::model::occ::getDistance
      //
      // Find the minimal distance between shape with `dim1' and `tag1' and shape
      // with `dim2' and `tag2' and the according coordinates. Return the distance
      // in `distance' and the coordinate of the points as `x1', `y1', `z1' and
      // `x2', `y2', `z2'.
      CMSH_API void getDistance(const int dim1,
                                const int tag1,
                                const int dim2,
                                const int tag2,
                                double & distance,
                                double & x1,
                                double & y1,
                                double & z1,
                                double & x2,
                                double & y2,
                                double & z2);

      // cmsh::model::occ::fuse
      //
      // Compute the boolean union (the fusion) of the entities `objectDimTags' and
      // `toolDimTags' (vectors of (dim, tag) pairs) in the OpenCASCADE CAD
      // representation. Return the resulting entities in `outDimTags'. If `tag' is
      // positive, try to set the tag explicitly (only valid if the boolean
      // operation results in a single entity). Remove the object if `removeObject'
      // is set. Remove the tool if `removeTool' is set.
      CMSH_API void fuse(const cmsh::vectorpair & objectDimTags,
                         const cmsh::vectorpair & toolDimTags,
                         cmsh::vectorpair & outDimTags,
                         std::vector<cmsh::vectorpair> & outDimTagsMap,
                         const int tag = -1,
                         const bool removeObject = true,
                         const bool removeTool = true);

      // cmsh::model::occ::intersect
      //
      // Compute the boolean intersection (the common parts) of the entities
      // `objectDimTags' and `toolDimTags' (vectors of (dim, tag) pairs) in the
      // OpenCASCADE CAD representation. Return the resulting entities in
      // `outDimTags'. If `tag' is positive, try to set the tag explicitly (only
      // valid if the boolean operation results in a single entity). Remove the
      // object if `removeObject' is set. Remove the tool if `removeTool' is set.
      CMSH_API void intersect(const cmsh::vectorpair & objectDimTags,
                              const cmsh::vectorpair & toolDimTags,
                              cmsh::vectorpair & outDimTags,
                              std::vector<cmsh::vectorpair> & outDimTagsMap,
                              const int tag = -1,
                              const bool removeObject = true,
                              const bool removeTool = true);

      // cmsh::model::occ::cut
      //
      // Compute the boolean difference between the entities `objectDimTags' and
      // `toolDimTags' (given as vectors of (dim, tag) pairs) in the OpenCASCADE
      // CAD representation. Return the resulting entities in `outDimTags'. If
      // `tag' is positive, try to set the tag explicitly (only valid if the
      // boolean operation results in a single entity). Remove the object if
      // `removeObject' is set. Remove the tool if `removeTool' is set.
      CMSH_API void cut(const cmsh::vectorpair & objectDimTags,
                        const cmsh::vectorpair & toolDimTags,
                        cmsh::vectorpair & outDimTags,
                        std::vector<cmsh::vectorpair> & outDimTagsMap,
                        const int tag = -1,
                        const bool removeObject = true,
                        const bool removeTool = true);

      // cmsh::model::occ::fragment
      //
      // Compute the boolean fragments (general fuse) resulting from the
      // intersection of the entities `objectDimTags' and `toolDimTags' (given as
      // vectors of (dim, tag) pairs) in the OpenCASCADE CAD representation, making
      // all interfaces conformal. When applied to entities of different
      // dimensions, the lower dimensional entities will be automatically embedded
      // in the higher dimensional entities if they are not on their boundary.
      // Return the resulting entities in `outDimTags'. If `tag' is positive, try
      // to set the tag explicitly (only valid if the boolean operation results in
      // a single entity). Remove the object if `removeObject' is set. Remove the
      // tool if `removeTool' is set.
      CMSH_API void fragment(const cmsh::vectorpair & objectDimTags,
                             const cmsh::vectorpair & toolDimTags,
                             cmsh::vectorpair & outDimTags,
                             std::vector<cmsh::vectorpair> & outDimTagsMap,
                             const int tag = -1,
                             const bool removeObject = true,
                             const bool removeTool = true);

      // cmsh::model::occ::translate
      //
      // Translate the entities `dimTags' (given as a vector of (dim, tag) pairs)
      // in the OpenCASCADE CAD representation along (`dx', `dy', `dz').
      CMSH_API void translate(const cmsh::vectorpair & dimTags,
                              const double dx,
                              const double dy,
                              const double dz);

      // cmsh::model::occ::rotate
      //
      // Rotate the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the OpenCASCADE CAD representation by `angle' radians around the axis of
      // revolution defined by the point (`x', `y', `z') and the direction (`ax',
      // `ay', `az').
      CMSH_API void rotate(const cmsh::vectorpair & dimTags,
                           const double x,
                           const double y,
                           const double z,
                           const double ax,
                           const double ay,
                           const double az,
                           const double angle);

      // cmsh::model::occ::dilate
      //
      // Scale the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the OpenCASCADE CAD representation by factors `a', `b' and `c' along the
      // three coordinate axes; use (`x', `y', `z') as the center of the homothetic
      // transformation.
      CMSH_API void dilate(const cmsh::vectorpair & dimTags,
                           const double x,
                           const double y,
                           const double z,
                           const double a,
                           const double b,
                           const double c);

      // cmsh::model::occ::mirror
      //
      // Mirror the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the OpenCASCADE CAD representation, with respect to the plane of equation
      // `a' * x + `b' * y + `c' * z + `d' = 0.
      CMSH_API void mirror(const cmsh::vectorpair & dimTags,
                           const double a,
                           const double b,
                           const double c,
                           const double d);

      // cmsh::model::occ::symmetrize
      //
      // Mirror the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the OpenCASCADE CAD representation, with respect to the plane of equation
      // `a' * x + `b' * y + `c' * z + `d' = 0. (This is a deprecated synonym for
      // `mirror'.)
      CMSH_API void symmetrize(const cmsh::vectorpair & dimTags,
                               const double a,
                               const double b,
                               const double c,
                               const double d);

      // cmsh::model::occ::affineTransform
      //
      // Apply a general affine transformation matrix `affineTransform' (16 entries
      // of a 4x4 matrix, by row; only the 12 first can be provided for
      // convenience) to the entities `dimTags' (given as a vector of (dim, tag)
      // pairs) in the OpenCASCADE CAD representation.
      CMSH_API void affineTransform(const cmsh::vectorpair & dimTags,
                                    const std::vector<double> & affineTransform);

      // cmsh::model::occ::copy
      //
      // Copy the entities `dimTags' in the OpenCASCADE CAD representation; the new
      // entities are returned in `outDimTags'.
      CMSH_API void copy(const cmsh::vectorpair & dimTags,
                         cmsh::vectorpair & outDimTags);

      // cmsh::model::occ::remove
      //
      // Remove the entities `dimTags' (given as a vector of (dim, tag) pairs) in
      // the OpenCASCADE CAD representation, provided that they are not on the
      // boundary of higher-dimensional entities. If `recursive' is true, remove
      // all the entities on their boundaries, down to dimension 0.
      CMSH_API void remove(const cmsh::vectorpair & dimTags,
                           const bool recursive = false);

      // cmsh::model::occ::removeAllDuplicates
      //
      // Remove all duplicate entities in the OpenCASCADE CAD representation
      // (different entities at the same geometrical location) after intersecting
      // (using boolean fragments) all highest dimensional entities.
      CMSH_API void removeAllDuplicates();

      // cmsh::model::occ::healShapes
      //
      // Apply various healing procedures to the entities `dimTags' (given as a
      // vector of (dim, tag) pairs), or to all the entities in the model if
      // `dimTags' is empty, in the OpenCASCADE CAD representation. Return the
      // healed entities in `outDimTags'.
      CMSH_API void healShapes(cmsh::vectorpair & outDimTags,
                               const cmsh::vectorpair & dimTags = cmsh::vectorpair(),
                               const double tolerance = 1e-8,
                               const bool fixDegenerated = true,
                               const bool fixSmallEdges = true,
                               const bool fixSmallFaces = true,
                               const bool sewFaces = true,
                               const bool makeSolids = true);

      // cmsh::model::occ::convertToNURBS
      //
      // Convert the entities `dimTags' to NURBS.
      CMSH_API void convertToNURBS(const cmsh::vectorpair & dimTags);

      // cmsh::model::occ::importShapes
      //
      // Import BREP, STEP or IGES shapes from the file `fileName' in the
      // OpenCASCADE CAD representation. The imported entities are returned in
      // `outDimTags', as a vector of (dim, tag) pairs. If the optional argument
      // `highestDimOnly' is set, only import the highest dimensional entities in
      // the file. The optional argument `format' can be used to force the format
      // of the file (currently "brep", "step" or "iges").
      CMSH_API void importShapes(const std::string & fileName,
                                 cmsh::vectorpair & outDimTags,
                                 const bool highestDimOnly = true,
                                 const std::string & format = "");

      // cmsh::model::occ::importShapesNativePointer
      //
      // Import an OpenCASCADE `shape' by providing a pointer to a native
      // OpenCASCADE `TopoDS_Shape' object (passed as a pointer to void). The
      // imported entities are returned in `outDimTags' as a vector of (dim, tag)
      // pairs. If the optional argument `highestDimOnly' is set, only import the
      // highest dimensional entities in `shape'. In Python, this function can be
      // used for integration with PythonOCC, in which the SwigPyObject pointer of
      // `TopoDS_Shape' must be passed as an int to `shape', i.e., `shape =
      // int(pythonocc_shape.this)'. Warning: this function is unsafe, as providing
      // an invalid pointer will lead to undefined behavior.
      CMSH_API void importShapesNativePointer(const void * shape,
                                              cmsh::vectorpair & outDimTags,
                                              const bool highestDimOnly = true);

      // cmsh::model::occ::getEntities
      //
      // Get all the OpenCASCADE entities. If `dim' is >= 0, return only the
      // entities of the specified dimension (e.g. points if `dim' == 0). The
      // entities are returned as a vector of (dim, tag) pairs.
      CMSH_API void getEntities(cmsh::vectorpair & dimTags,
                                const int dim = -1);

      // cmsh::model::occ::getEntitiesInBoundingBox
      //
      // Get the OpenCASCADE entities in the bounding box defined by the two points
      // (`xmin', `ymin', `zmin') and (`xmax', `ymax', `zmax'). If `dim' is >= 0,
      // return only the entities of the specified dimension (e.g. points if `dim'
      // == 0).
      CMSH_API void getEntitiesInBoundingBox(const double xmin,
                                             const double ymin,
                                             const double zmin,
                                             const double xmax,
                                             const double ymax,
                                             const double zmax,
                                             cmsh::vectorpair & dimTags,
                                             const int dim = -1);

      // cmsh::model::occ::getBoundingBox
      //
      // Get the bounding box (`xmin', `ymin', `zmin'), (`xmax', `ymax', `zmax') of
      // the OpenCASCADE entity of dimension `dim' and tag `tag'.
      CMSH_API void getBoundingBox(const int dim,
                                   const int tag,
                                   double & xmin,
                                   double & ymin,
                                   double & zmin,
                                   double & xmax,
                                   double & ymax,
                                   double & zmax);

      // cmsh::model::occ::getCurveLoops
      //
      // Get the tags `curveLoopTags' of the curve loops making up the surface of
      // tag `surfaceTag', as well as the tags `curveTags' of the curves making up
      // each curve loop.
      CMSH_API void getCurveLoops(const int surfaceTag,
                                  std::vector<int> & curveLoopTags,
                                  std::vector<std::vector<int> > & curveTags);

      // cmsh::model::occ::getSurfaceLoops
      //
      // Get the tags `surfaceLoopTags' of the surface loops making up the volume
      // of tag `volumeTag', as well as the tags `surfaceTags' of the surfaces
      // making up each surface loop.
      CMSH_API void getSurfaceLoops(const int volumeTag,
                                    std::vector<int> & surfaceLoopTags,
                                    std::vector<std::vector<int> > & surfaceTags);

      // cmsh::model::occ::getMass
      //
      // Get the mass of the OpenCASCADE entity of dimension `dim' and tag `tag'.
      // If no density is attached to the entity (the default), the value
      // corresponds respectively to the length, area and volume for `dim' = 1, 2
      // and 3.
      CMSH_API void getMass(const int dim,
                            const int tag,
                            double & mass);

      // cmsh::model::occ::getCenterOfMass
      //
      // Get the center of mass of the OpenCASCADE entity of dimension `dim' and
      // tag `tag'.
      CMSH_API void getCenterOfMass(const int dim,
                                    const int tag,
                                    double & x,
                                    double & y,
                                    double & z);

      // cmsh::model::occ::getMatrixOfInertia
      //
      // Get the matrix of inertia (by row) of the OpenCASCADE entity of dimension
      // `dim' and tag `tag'.
      CMSH_API void getMatrixOfInertia(const int dim,
                                       const int tag,
                                       std::vector<double> & mat);

      // cmsh::model::occ::getMaxTag
      //
      // Get the maximum tag of entities of dimension `dim' in the OpenCASCADE CAD
      // representation.
      CMSH_API int getMaxTag(const int dim);

      // cmsh::model::occ::setMaxTag
      //
      // Set the maximum tag `maxTag' for entities of dimension `dim' in the
      // OpenCASCADE CAD representation.
      CMSH_API void setMaxTag(const int dim,
                              const int maxTag);

      // cmsh::model::occ::synchronize
      //
      // Synchronize the OpenCASCADE CAD representation with the current Gmsh
      // model. This can be called at any time, but since it involves a non trivial
      // amount of processing, the number of synchronization points should normally
      // be minimized. Without synchronization the entities in the OpenCASCADE CAD
      // representation are not available to any function outside of the
      // OpenCASCADE CAD kernel functions.
      CMSH_API void synchronize();

      namespace mesh { // OpenCASCADE CAD kernel meshing constraints

        // cmsh::model::occ::mesh::setSize
        //
        // Set a mesh size constraint on the entities `dimTags' (given as a vector
        // of (dim, tag) pairs) in the OpenCASCADE CAD representation. Currently
        // only entities of dimension 0 (points) are handled.
        CMSH_API void setSize(const cmsh::vectorpair & dimTags,
                              const double size);

      } // namespace mesh

    } // namespace occ

  } // namespace model

  namespace view { // Post-processing view functions

    // cmsh::view::add
    //
    // Add a new post-processing view, with name `name'. If `tag' is positive use
    // it (and remove the view with that tag if it already exists), otherwise
    // associate a new tag. Return the view tag.
    CMSH_API int add(const std::string & name,
                     const int tag = -1);

    // cmsh::view::remove
    //
    // Remove the view with tag `tag'.
    CMSH_API void remove(const int tag);

    // cmsh::view::getIndex
    //
    // Get the index of the view with tag `tag' in the list of currently loaded
    // views. This dynamic index (it can change when views are removed) is used to
    // access view options.
    CMSH_API int getIndex(const int tag);

    // cmsh::view::getTags
    //
    // Get the tags of all views.
    CMSH_API void getTags(std::vector<int> & tags);

    // cmsh::view::addModelData
    //
    // Add model-based post-processing data to the view with tag `tag'. `modelName'
    // identifies the model the data is attached to. `dataType' specifies the type
    // of data, currently either "NodeData", "ElementData" or "ElementNodeData".
    // `step' specifies the identifier (>= 0) of the data in a sequence. `tags'
    // gives the tags of the nodes or elements in the mesh to which the data is
    // associated. `data' is a vector of the same length as `tags': each entry is
    // the vector of double precision numbers representing the data associated with
    // the corresponding tag. The optional `time' argument associate a time value
    // with the data. `numComponents' gives the number of data components (1 for
    // scalar data, 3 for vector data, etc.) per entity; if negative, it is
    // automatically inferred (when possible) from the input data. `partition'
    // allows one to specify data in several sub-sets.
    CMSH_API void addModelData(const int tag,
                               const int step,
                               const std::string & modelName,
                               const std::string & dataType,
                               const std::vector<std::size_t> & tags,
                               const std::vector<std::vector<double> > & data,
                               const double time = 0.,
                               const int numComponents = -1,
                               const int partition = 0);

    // cmsh::view::addHomogeneousModelData
    //
    // Add homogeneous model-based post-processing data to the view with tag `tag'.
    // The arguments have the same meaning as in `addModelData', except that `data'
    // is supposed to be homogeneous and is thus flattened in a single vector. For
    // data types that can lead to different data sizes per tag (like
    // "ElementNodeData"), the data should be padded.
    CMSH_API void addHomogeneousModelData(const int tag,
                                          const int step,
                                          const std::string & modelName,
                                          const std::string & dataType,
                                          const std::vector<std::size_t> & tags,
                                          const std::vector<double> & data,
                                          const double time = 0.,
                                          const int numComponents = -1,
                                          const int partition = 0);

    // cmsh::view::getModelData
    //
    // Get model-based post-processing data from the view with tag `tag' at step
    // `step'. Return the `data' associated to the nodes or the elements with tags
    // `tags', as well as the `dataType' and the number of components
    // `numComponents'.
    CMSH_API void getModelData(const int tag,
                               const int step,
                               std::string & dataType,
                               std::vector<std::size_t> & tags,
                               std::vector<std::vector<double> > & data,
                               double & time,
                               int & numComponents);

    // cmsh::view::getHomogeneousModelData
    //
    // Get homogeneous model-based post-processing data from the view with tag
    // `tag' at step `step'. The arguments have the same meaning as in
    // `getModelData', except that `data' is returned flattened in a single vector,
    // with the appropriate padding if necessary.
    CMSH_API void getHomogeneousModelData(const int tag,
                                          const int step,
                                          std::string & dataType,
                                          std::vector<std::size_t> & tags,
                                          std::vector<double> & data,
                                          double & time,
                                          int & numComponents);

    // cmsh::view::addListData
    //
    // Add list-based post-processing data to the view with tag `tag'. List-based
    // datasets are independent from any model and any mesh. `dataType' identifies
    // the data by concatenating the field type ("S" for scalar, "V" for vector,
    // "T" for tensor) and the element type ("P" for point, "L" for line, "T" for
    // triangle, "S" for tetrahedron, "I" for prism, "H" for hexaHedron, "Y" for
    // pyramid). For example `dataType' should be "ST" for a scalar field on
    // triangles. `numEle' gives the number of elements in the data. `data'
    // contains the data for the `numEle' elements, concatenated, with node
    // coordinates followed by values per node, repeated for each step: [e1x1, ...,
    // e1xn, e1y1, ..., e1yn, e1z1, ..., e1zn, e1v1..., e1vN, e2x1, ...].
    CMSH_API void addListData(const int tag,
                              const std::string & dataType,
                              const int numEle,
                              const std::vector<double> & data);

    // cmsh::view::getListData
    //
    // Get list-based post-processing data from the view with tag `tag'. Return the
    // types `dataTypes', the number of elements `numElements' for each data type
    // and the `data' for each data type. If `returnAdaptive' is set, return the
    // data obtained after adaptive refinement, if available.
    CMSH_API void getListData(const int tag,
                              std::vector<std::string> & dataType,
                              std::vector<int> & numElements,
                              std::vector<std::vector<double> > & data,
                              const bool returnAdaptive = false);

    // cmsh::view::addListDataString
    //
    // Add a string to a list-based post-processing view with tag `tag'. If `coord'
    // contains 3 coordinates the string is positioned in the 3D model space ("3D
    // string"); if it contains 2 coordinates it is positioned in the 2D graphics
    // viewport ("2D string"). `data' contains one or more (for multistep views)
    // strings. `style' contains key-value pairs of styling parameters,
    // concatenated. Available keys are "Font" (possible values: "Times-Roman",
    // "Times-Bold", "Times-Italic", "Times-BoldItalic", "Helvetica", "Helvetica-
    // Bold", "Helvetica-Oblique", "Helvetica-BoldOblique", "Courier", "Courier-
    // Bold", "Courier-Oblique", "Courier-BoldOblique", "Symbol", "ZapfDingbats",
    // "Screen"), "FontSize" and "Align" (possible values: "Left" or "BottomLeft",
    // "Center" or "BottomCenter", "Right" or "BottomRight", "TopLeft",
    // "TopCenter", "TopRight", "CenterLeft", "CenterCenter", "CenterRight").
    CMSH_API void addListDataString(const int tag,
                                    const std::vector<double> & coord,
                                    const std::vector<std::string> & data,
                                    const std::vector<std::string> & style = std::vector<std::string>());

    // cmsh::view::getListDataStrings
    //
    // Get list-based post-processing data strings (2D strings if `dim' == 2, 3D
    // strings if `dim' = 3) from the view with tag `tag'. Return the coordinates
    // in `coord', the strings in `data' and the styles in `style'.
    CMSH_API void getListDataStrings(const int tag,
                                     const int dim,
                                     std::vector<double> & coord,
                                     std::vector<std::string> & data,
                                     std::vector<std::string> & style);

    // cmsh::view::setInterpolationMatrices
    //
    // Set interpolation matrices for the element family `type' ("Line",
    // "Triangle", "Quadrangle", "Tetrahedron", "Hexahedron", "Prism", "Pyramid")
    // in the view `tag'. The approximation of the values over an element is
    // written as a linear combination of `d' basis functions f_i(u, v, w) = sum_(j
    // = 0, ..., `d' - 1) `coef'[i][j] u^`exp'[j][0] v^`exp'[j][1] w^`exp'[j][2], i
    // = 0, ..., `d'-1, with u, v, w the coordinates in the reference element. The
    // `coef' matrix (of size `d' x `d') and the `exp' matrix (of size `d' x 3) are
    // stored as vectors, by row. If `dGeo' is positive, use `coefGeo' and `expGeo'
    // to define the interpolation of the x, y, z coordinates of the element in
    // terms of the u, v, w coordinates, in exactly the same way. If `d' < 0,
    // remove the interpolation matrices.
    CMSH_API void setInterpolationMatrices(const int tag,
                                           const std::string & type,
                                           const int d,
                                           const std::vector<double> & coef,
                                           const std::vector<double> & exp,
                                           const int dGeo = 0,
                                           const std::vector<double> & coefGeo = std::vector<double>(),
                                           const std::vector<double> & expGeo = std::vector<double>());

    // cmsh::view::addAlias
    //
    // Add a post-processing view as an `alias' of the reference view with tag
    // `refTag'. If `copyOptions' is set, copy the options of the reference view.
    // If `tag' is positive use it (and remove the view with that tag if it already
    // exists), otherwise associate a new tag. Return the view tag.
    CMSH_API int addAlias(const int refTag,
                          const bool copyOptions = false,
                          const int tag = -1);

    // cmsh::view::combine
    //
    // Combine elements (if `what' == "elements") or steps (if `what' == "steps")
    // of all views (`how' == "all"), all visible views (`how' == "visible") or all
    // views having the same name (`how' == "name"). Remove original views if
    // `remove' is set.
    CMSH_API void combine(const std::string & what,
                          const std::string & how,
                          const bool remove = true,
                          const bool copyOptions = true);

    // cmsh::view::probe
    //
    // Probe the view `tag' for its `values' at point (`x', `y', `z'). If no match
    // is found, `value' is returned empty. Return only the value at step `step' is
    // `step' is positive. Return only values with `numComp' if `numComp' is
    // positive. Return the gradient of the `values' if `gradient' is set. If
    // `distanceMax' is zero, only return a result if an exact match inside an
    // element in the view is found; if `distanceMax' is positive and an exact
    // match is not found, return the value at the closest node if it is closer
    // than `distanceMax'; if `distanceMax' is negative and an exact match is not
    // found, always return the value at the closest node. The distance to the
    // match is returned in `distance'. Return the result from the element
    // described by its coordinates if `xElementCoord', `yElementCoord' and
    // `zElementCoord' are provided. If `dim' is >= 0, return only matches from
    // elements of the specified dimension.
    CMSH_API void probe(const int tag,
                        const double x,
                        const double y,
                        const double z,
                        std::vector<double> & values,
                        double & distance,
                        const int step = -1,
                        const int numComp = -1,
                        const bool gradient = false,
                        const double distanceMax = 0.,
                        const std::vector<double> & xElemCoord = std::vector<double>(),
                        const std::vector<double> & yElemCoord = std::vector<double>(),
                        const std::vector<double> & zElemCoord = std::vector<double>(),
                        const int dim = -1);

    // cmsh::view::write
    //
    // Write the view to a file `fileName'. The export format is determined by the
    // file extension. Append to the file if `append' is set.
    CMSH_API void write(const int tag,
                        const std::string & fileName,
                        const bool append = false);

    // cmsh::view::setVisibilityPerWindow
    //
    // Set the global visibility of the view `tag' per window to `value', where
    // `windowIndex' identifies the window in the window list.
    CMSH_API void setVisibilityPerWindow(const int tag,
                                         const int value,
                                         const int windowIndex = 0);

    namespace option { // View option handling functions

      // cmsh::view::option::setNumber
      //
      // Set the numerical option `name' to value `value' for the view with tag
      // `tag'.
      CMSH_API void setNumber(const int tag,
                              const std::string & name,
                              const double value);

      // cmsh::view::option::getNumber
      //
      // Get the `value' of the numerical option `name' for the view with tag
      // `tag'.
      CMSH_API void getNumber(const int tag,
                              const std::string & name,
                              double & value);

      // cmsh::view::option::setString
      //
      // Set the string option `name' to value `value' for the view with tag `tag'.
      CMSH_API void setString(const int tag,
                              const std::string & name,
                              const std::string & value);

      // cmsh::view::option::getString
      //
      // Get the `value' of the string option `name' for the view with tag `tag'.
      CMSH_API void getString(const int tag,
                              const std::string & name,
                              std::string & value);

      // cmsh::view::option::setColor
      //
      // Set the color option `name' to the RGBA value (`r', `g', `b', `a') for the
      // view with tag `tag', where where `r', `g', `b' and `a' should be integers
      // between 0 and 255.
      CMSH_API void setColor(const int tag,
                             const std::string & name,
                             const int r,
                             const int g,
                             const int b,
                             const int a = 255);

      // cmsh::view::option::getColor
      //
      // Get the `r', `g', `b', `a' value of the color option `name' for the view
      // with tag `tag'.
      CMSH_API void getColor(const int tag,
                             const std::string & name,
                             int & r,
                             int & g,
                             int & b,
                             int & a);

      // cmsh::view::option::copy
      //
      // Copy the options from the view with tag `refTag' to the view with tag
      // `tag'.
      CMSH_API void copy(const int refTag,
                         const int tag);

    } // namespace option

  } // namespace view

  namespace plugin { // Plugin functions

    // cmsh::plugin::setNumber
    //
    // Set the numerical option `option' to the value `value' for plugin `name'.
    // Plugins available in the official Gmsh release are listed in the "Gmsh
    // plugins" chapter of the Gmsh reference manual
    // (https://cmsh.info/doc/texinfo/cmsh.html#Gmsh-plugins).
    CMSH_API void setNumber(const std::string & name,
                            const std::string & option,
                            const double value);

    // cmsh::plugin::setString
    //
    // Set the string option `option' to the value `value' for plugin `name'.
    // Plugins available in the official Gmsh release are listed in the "Gmsh
    // plugins" chapter of the Gmsh reference manual
    // (https://cmsh.info/doc/texinfo/cmsh.html#Gmsh-plugins).
    CMSH_API void setString(const std::string & name,
                            const std::string & option,
                            const std::string & value);

    // cmsh::plugin::run
    //
    // Run the plugin `name'. Return the tag of the created view (if any). Plugins
    // available in the official Gmsh release are listed in the "Gmsh plugins"
    // chapter of the Gmsh reference manual
    // (https://cmsh.info/doc/texinfo/cmsh.html#Gmsh-plugins).
    CMSH_API int run(const std::string & name);

  } // namespace plugin

  namespace graphics { // Graphics functions

    // cmsh::graphics::draw
    //
    // Draw all the OpenGL scenes.
    CMSH_API void draw();

  } // namespace graphics

  namespace fltk { // FLTK graphical user interface functions

    // cmsh::fltk::initialize
    //
    // Create the FLTK graphical user interface. Can only be called in the main
    // thread.
    CMSH_API void initialize();

    // cmsh::fltk::finalize
    //
    // Close the FLTK graphical user interface. Can only be called in the main
    // thread.
    CMSH_API void finalize();

    // cmsh::fltk::wait
    //
    // Wait at most `time' seconds for user interface events and return. If `time'
    // < 0, wait indefinitely. First automatically create the user interface if it
    // has not yet been initialized. Can only be called in the main thread.
    CMSH_API void wait(const double time = -1.);

    // cmsh::fltk::update
    //
    // Update the user interface (potentially creating new widgets and windows).
    // First automatically create the user interface if it has not yet been
    // initialized. Can only be called in the main thread: use `awake("update")' to
    // trigger an update of the user interface from another thread.
    CMSH_API void update();

    // cmsh::fltk::awake
    //
    // Awake the main user interface thread and process pending events, and
    // optionally perform an action (currently the only `action' allowed is
    // "update").
    CMSH_API void awake(const std::string & action = "");

    // cmsh::fltk::lock
    //
    // Block the current thread until it can safely modify the user interface.
    CMSH_API void lock();

    // cmsh::fltk::unlock
    //
    // Release the lock that was set using lock.
    CMSH_API void unlock();

    // cmsh::fltk::run
    //
    // Run the event loop of the graphical user interface, i.e. repeatedly call
    // `wait()'. First automatically create the user interface if it has not yet
    // been initialized. Can only be called in the main thread.
    CMSH_API void run();

    // cmsh::fltk::isAvailable
    //
    // Check if the user interface is available (e.g. to detect if it has been
    // closed).
    CMSH_API int isAvailable();

    // cmsh::fltk::selectEntities
    //
    // Select entities in the user interface. Return the selected entities as a
    // vector of (dim, tag) pairs. If `dim' is >= 0, return only the entities of
    // the specified dimension (e.g. points if `dim' == 0).
    CMSH_API int selectEntities(cmsh::vectorpair & dimTags,
                                const int dim = -1);

    // cmsh::fltk::selectElements
    //
    // Select elements in the user interface.
    CMSH_API int selectElements(std::vector<std::size_t> & elementTags);

    // cmsh::fltk::selectViews
    //
    // Select views in the user interface.
    CMSH_API int selectViews(std::vector<int> & viewTags);

    // cmsh::fltk::splitCurrentWindow
    //
    // Split the current window horizontally (if `how' == "h") or vertically (if
    // `how' == "v"), using ratio `ratio'. If `how' == "u", restore a single
    // window.
    CMSH_API void splitCurrentWindow(const std::string & how = "v",
                                     const double ratio = 0.5);

    // cmsh::fltk::setCurrentWindow
    //
    // Set the current window by speficying its index (starting at 0) in the list
    // of all windows. When new windows are created by splits, new windows are
    // appended at the end of the list.
    CMSH_API void setCurrentWindow(const int windowIndex = 0);

    // cmsh::fltk::setStatusMessage
    //
    // Set a status message in the current window. If `graphics' is set, display
    // the message inside the graphic window instead of the status bar.
    CMSH_API void setStatusMessage(const std::string & message,
                                   const bool graphics = false);

    // cmsh::fltk::showContextWindow
    //
    // Show context window for the entity of dimension `dim' and tag `tag'.
    CMSH_API void showContextWindow(const int dim,
                                    const int tag);

    // cmsh::fltk::openTreeItem
    //
    // Open the `name' item in the menu tree.
    CMSH_API void openTreeItem(const std::string & name);

    // cmsh::fltk::closeTreeItem
    //
    // Close the `name' item in the menu tree.
    CMSH_API void closeTreeItem(const std::string & name);

  } // namespace fltk

  namespace parser { // Parser functions

    // cmsh::parser::getNames
    //
    // Get the names of the variables in the Gmsh parser matching the `search'
    // regular expression. If `search' is empty, return all the names.
    CMSH_API void getNames(std::vector<std::string> & names,
                           const std::string & search = "");

    // cmsh::parser::setNumber
    //
    // Set the value of the number variable `name' in the Gmsh parser. Create the
    // variable if it does not exist; update the value if the variable exists.
    CMSH_API void setNumber(const std::string & name,
                            const std::vector<double> & value);

    // cmsh::parser::setString
    //
    // Set the value of the string variable `name' in the Gmsh parser. Create the
    // variable if it does not exist; update the value if the variable exists.
    CMSH_API void setString(const std::string & name,
                            const std::vector<std::string> & value);

    // cmsh::parser::getNumber
    //
    // Get the value of the number variable `name' from the Gmsh parser. Return an
    // empty vector if the variable does not exist.
    CMSH_API void getNumber(const std::string & name,
                            std::vector<double> & value);

    // cmsh::parser::getString
    //
    // Get the value of the string variable `name' from the Gmsh parser. Return an
    // empty vector if the variable does not exist.
    CMSH_API void getString(const std::string & name,
                            std::vector<std::string> & value);

    // cmsh::parser::clear
    //
    // Clear all the Gmsh parser variables, or remove a single variable if `name'
    // is given.
    CMSH_API void clear(const std::string & name = "");

    // cmsh::parser::parse
    //
    // Parse the file `fileName' with the Gmsh parser.
    CMSH_API void parse(const std::string & fileName);

  } // namespace parser

  namespace onelab { // ONELAB server functions

    // cmsh::onelab::set
    //
    // Set one or more parameters in the ONELAB database, encoded in `format'.
    CMSH_API void set(const std::string & data,
                      const std::string & format = "json");

    // cmsh::onelab::get
    //
    // Get all the parameters (or a single one if `name' is specified) from the
    // ONELAB database, encoded in `format'.
    CMSH_API void get(std::string & data,
                      const std::string & name = "",
                      const std::string & format = "json");

    // cmsh::onelab::getNames
    //
    // Get the names of the parameters in the ONELAB database matching the `search'
    // regular expression. If `search' is empty, return all the names.
    CMSH_API void getNames(std::vector<std::string> & names,
                           const std::string & search = "");

    // cmsh::onelab::setNumber
    //
    // Set the value of the number parameter `name' in the ONELAB database. Create
    // the parameter if it does not exist; update the value if the parameter
    // exists.
    CMSH_API void setNumber(const std::string & name,
                            const std::vector<double> & value);

    // cmsh::onelab::setString
    //
    // Set the value of the string parameter `name' in the ONELAB database. Create
    // the parameter if it does not exist; update the value if the parameter
    // exists.
    CMSH_API void setString(const std::string & name,
                            const std::vector<std::string> & value);

    // cmsh::onelab::getNumber
    //
    // Get the value of the number parameter `name' from the ONELAB database.
    // Return an empty vector if the parameter does not exist.
    CMSH_API void getNumber(const std::string & name,
                            std::vector<double> & value);

    // cmsh::onelab::getString
    //
    // Get the value of the string parameter `name' from the ONELAB database.
    // Return an empty vector if the parameter does not exist.
    CMSH_API void getString(const std::string & name,
                            std::vector<std::string> & value);

    // cmsh::onelab::getChanged
    //
    // Check if any parameters in the ONELAB database used by the client `name'
    // have been changed.
    CMSH_API int getChanged(const std::string & name);

    // cmsh::onelab::setChanged
    //
    // Set the changed flag to value `value' for all the parameters in the ONELAB
    // database used by the client `name'.
    CMSH_API void setChanged(const std::string & name,
                             const int value);

    // cmsh::onelab::clear
    //
    // Clear the ONELAB database, or remove a single parameter if `name' is given.
    CMSH_API void clear(const std::string & name = "");

    // cmsh::onelab::run
    //
    // Run a ONELAB client. If `name' is provided, create a new ONELAB client with
    // name `name' and executes `command'. If not, try to run a client that might
    // be linked to the processed input files.
    CMSH_API void run(const std::string & name = "",
                      const std::string & command = "");

  } // namespace onelab

  namespace logger { // Information logging functions

    // cmsh::logger::write
    //
    // Write a `message'. `level' can be "info", "warning" or "error".
    CMSH_API void write(const std::string & message,
                        const std::string & level = "info");

    // cmsh::logger::start
    //
    // Start logging messages.
    CMSH_API void start();

    // cmsh::logger::get
    //
    // Get logged messages.
    CMSH_API void get(std::vector<std::string> & log);

    // cmsh::logger::stop
    //
    // Stop logging messages.
    CMSH_API void stop();

    // cmsh::logger::getWallTime
    //
    // Return wall clock time (in s).
    CMSH_API double getWallTime();

    // cmsh::logger::getCpuTime
    //
    // Return CPU time (in s).
    CMSH_API double getCpuTime();

    // cmsh::logger::getMemory
    //
    // Return memory usage (in Mb).
    CMSH_API double getMemory();

    // cmsh::logger::getTotalMemory
    //
    // Return total available memory (in Mb).
    CMSH_API double getTotalMemory();

    // cmsh::logger::getLastError
    //
    // Return last error message, if any.
    CMSH_API void getLastError(std::string & error);

  } // namespace logger

} // namespace cmsh

#endif
